filtersets.py 75 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344
  1. import django_filters
  2. from django.contrib.contenttypes.models import ContentType
  3. from django.utils.translation import gettext as _
  4. from drf_spectacular.types import OpenApiTypes
  5. from drf_spectacular.utils import extend_schema_field
  6. from circuits.models import CircuitTermination
  7. from extras.filtersets import LocalConfigContextFilterSet
  8. from extras.models import ConfigTemplate
  9. from ipam.filtersets import PrimaryIPFilterSet
  10. from ipam.models import ASN, IPAddress, VLANTranslationPolicy, VRF
  11. from netbox.choices import ColorChoices
  12. from netbox.filtersets import (
  13. BaseFilterSet, ChangeLoggedModelFilterSet, OrganizationalModelFilterSet, NetBoxModelFilterSet,
  14. )
  15. from tenancy.filtersets import TenancyFilterSet, ContactModelFilterSet
  16. from tenancy.models import *
  17. from users.models import User
  18. from utilities.filters import (
  19. ContentTypeFilter, MultiValueCharFilter, MultiValueMACAddressFilter, MultiValueNumberFilter, MultiValueWWNFilter,
  20. NumericArrayFilter, TreeNodeMultipleChoiceFilter,
  21. )
  22. from virtualization.models import Cluster, ClusterGroup
  23. from vpn.models import L2VPN
  24. from wireless.choices import WirelessRoleChoices, WirelessChannelChoices
  25. from wireless.models import WirelessLAN, WirelessLink
  26. from .choices import *
  27. from .constants import *
  28. from .models import *
  29. __all__ = (
  30. 'CableFilterSet',
  31. 'CabledObjectFilterSet',
  32. 'CableTerminationFilterSet',
  33. 'CommonInterfaceFilterSet',
  34. 'ConsoleConnectionFilterSet',
  35. 'ConsolePortFilterSet',
  36. 'ConsolePortTemplateFilterSet',
  37. 'ConsoleServerPortFilterSet',
  38. 'ConsoleServerPortTemplateFilterSet',
  39. 'DeviceBayFilterSet',
  40. 'DeviceBayTemplateFilterSet',
  41. 'DeviceFilterSet',
  42. 'DeviceRoleFilterSet',
  43. 'DeviceTypeFilterSet',
  44. 'FrontPortFilterSet',
  45. 'FrontPortTemplateFilterSet',
  46. 'InterfaceConnectionFilterSet',
  47. 'InterfaceFilterSet',
  48. 'InterfaceTemplateFilterSet',
  49. 'InventoryItemFilterSet',
  50. 'InventoryItemRoleFilterSet',
  51. 'InventoryItemTemplateFilterSet',
  52. 'LocationFilterSet',
  53. 'ManufacturerFilterSet',
  54. 'ModuleBayFilterSet',
  55. 'ModuleBayTemplateFilterSet',
  56. 'ModuleFilterSet',
  57. 'ModuleTypeFilterSet',
  58. 'PathEndpointFilterSet',
  59. 'PlatformFilterSet',
  60. 'PowerConnectionFilterSet',
  61. 'PowerFeedFilterSet',
  62. 'PowerOutletFilterSet',
  63. 'PowerOutletTemplateFilterSet',
  64. 'PowerPanelFilterSet',
  65. 'PowerPortFilterSet',
  66. 'PowerPortTemplateFilterSet',
  67. 'RackFilterSet',
  68. 'RackReservationFilterSet',
  69. 'RackRoleFilterSet',
  70. 'RackTypeFilterSet',
  71. 'RearPortFilterSet',
  72. 'RearPortTemplateFilterSet',
  73. 'RegionFilterSet',
  74. 'SiteFilterSet',
  75. 'SiteGroupFilterSet',
  76. 'VirtualChassisFilterSet',
  77. 'VirtualDeviceContextFilterSet',
  78. )
  79. class RegionFilterSet(OrganizationalModelFilterSet, ContactModelFilterSet):
  80. parent_id = django_filters.ModelMultipleChoiceFilter(
  81. queryset=Region.objects.all(),
  82. label=_('Parent region (ID)'),
  83. )
  84. parent = django_filters.ModelMultipleChoiceFilter(
  85. field_name='parent__slug',
  86. queryset=Region.objects.all(),
  87. to_field_name='slug',
  88. label=_('Parent region (slug)'),
  89. )
  90. ancestor_id = TreeNodeMultipleChoiceFilter(
  91. queryset=Region.objects.all(),
  92. field_name='parent',
  93. lookup_expr='in',
  94. label=_('Region (ID)'),
  95. )
  96. ancestor = TreeNodeMultipleChoiceFilter(
  97. queryset=Region.objects.all(),
  98. field_name='parent',
  99. lookup_expr='in',
  100. to_field_name='slug',
  101. label=_('Region (slug)'),
  102. )
  103. class Meta:
  104. model = Region
  105. fields = ('id', 'name', 'slug', 'description')
  106. class SiteGroupFilterSet(OrganizationalModelFilterSet, ContactModelFilterSet):
  107. parent_id = django_filters.ModelMultipleChoiceFilter(
  108. queryset=SiteGroup.objects.all(),
  109. label=_('Parent site group (ID)'),
  110. )
  111. parent = django_filters.ModelMultipleChoiceFilter(
  112. field_name='parent__slug',
  113. queryset=SiteGroup.objects.all(),
  114. to_field_name='slug',
  115. label=_('Parent site group (slug)'),
  116. )
  117. ancestor_id = TreeNodeMultipleChoiceFilter(
  118. queryset=SiteGroup.objects.all(),
  119. field_name='parent',
  120. lookup_expr='in',
  121. label=_('Site group (ID)'),
  122. )
  123. ancestor = TreeNodeMultipleChoiceFilter(
  124. queryset=SiteGroup.objects.all(),
  125. field_name='parent',
  126. lookup_expr='in',
  127. to_field_name='slug',
  128. label=_('Site group (slug)'),
  129. )
  130. class Meta:
  131. model = SiteGroup
  132. fields = ('id', 'name', 'slug', 'description')
  133. class SiteFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilterSet):
  134. status = django_filters.MultipleChoiceFilter(
  135. choices=SiteStatusChoices,
  136. null_value=None
  137. )
  138. region_id = TreeNodeMultipleChoiceFilter(
  139. queryset=Region.objects.all(),
  140. field_name='region',
  141. lookup_expr='in',
  142. label=_('Region (ID)'),
  143. )
  144. region = TreeNodeMultipleChoiceFilter(
  145. queryset=Region.objects.all(),
  146. lookup_expr='in',
  147. to_field_name='slug',
  148. label=_('Region (slug)'),
  149. )
  150. group_id = TreeNodeMultipleChoiceFilter(
  151. queryset=SiteGroup.objects.all(),
  152. field_name='group',
  153. lookup_expr='in',
  154. label=_('Group (ID)'),
  155. )
  156. group = TreeNodeMultipleChoiceFilter(
  157. queryset=SiteGroup.objects.all(),
  158. lookup_expr='in',
  159. to_field_name='slug',
  160. label=_('Group (slug)'),
  161. )
  162. asn = django_filters.ModelMultipleChoiceFilter(
  163. field_name='asns__asn',
  164. queryset=ASN.objects.all(),
  165. to_field_name='asn',
  166. label=_('AS (ID)'),
  167. )
  168. asn_id = django_filters.ModelMultipleChoiceFilter(
  169. field_name='asns',
  170. queryset=ASN.objects.all(),
  171. label=_('AS (ID)'),
  172. )
  173. time_zone = MultiValueCharFilter()
  174. class Meta:
  175. model = Site
  176. fields = ('id', 'name', 'slug', 'facility', 'latitude', 'longitude', 'description')
  177. def search(self, queryset, name, value):
  178. if not value.strip():
  179. return queryset
  180. qs_filter = (
  181. Q(name__icontains=value) |
  182. Q(facility__icontains=value) |
  183. Q(description__icontains=value) |
  184. Q(physical_address__icontains=value) |
  185. Q(shipping_address__icontains=value) |
  186. Q(comments__icontains=value)
  187. )
  188. try:
  189. qs_filter |= Q(asns__asn=int(value.strip()))
  190. except ValueError:
  191. pass
  192. return queryset.filter(qs_filter).distinct()
  193. class LocationFilterSet(TenancyFilterSet, ContactModelFilterSet, OrganizationalModelFilterSet):
  194. region_id = TreeNodeMultipleChoiceFilter(
  195. queryset=Region.objects.all(),
  196. field_name='site__region',
  197. lookup_expr='in',
  198. label=_('Region (ID)'),
  199. )
  200. region = TreeNodeMultipleChoiceFilter(
  201. queryset=Region.objects.all(),
  202. field_name='site__region',
  203. lookup_expr='in',
  204. to_field_name='slug',
  205. label=_('Region (slug)'),
  206. )
  207. site_group_id = TreeNodeMultipleChoiceFilter(
  208. queryset=SiteGroup.objects.all(),
  209. field_name='site__group',
  210. lookup_expr='in',
  211. label=_('Site group (ID)'),
  212. )
  213. site_group = TreeNodeMultipleChoiceFilter(
  214. queryset=SiteGroup.objects.all(),
  215. field_name='site__group',
  216. lookup_expr='in',
  217. to_field_name='slug',
  218. label=_('Site group (slug)'),
  219. )
  220. site_id = django_filters.ModelMultipleChoiceFilter(
  221. queryset=Site.objects.all(),
  222. label=_('Site (ID)'),
  223. )
  224. site = django_filters.ModelMultipleChoiceFilter(
  225. field_name='site__slug',
  226. queryset=Site.objects.all(),
  227. to_field_name='slug',
  228. label=_('Site (slug)'),
  229. )
  230. parent_id = django_filters.ModelMultipleChoiceFilter(
  231. queryset=Location.objects.all(),
  232. label=_('Parent location (ID)'),
  233. )
  234. parent = django_filters.ModelMultipleChoiceFilter(
  235. field_name='parent__slug',
  236. queryset=Location.objects.all(),
  237. to_field_name='slug',
  238. label=_('Parent location (slug)'),
  239. )
  240. ancestor_id = TreeNodeMultipleChoiceFilter(
  241. queryset=Location.objects.all(),
  242. field_name='parent',
  243. lookup_expr='in',
  244. label=_('Location (ID)'),
  245. )
  246. ancestor = TreeNodeMultipleChoiceFilter(
  247. queryset=Location.objects.all(),
  248. field_name='parent',
  249. lookup_expr='in',
  250. to_field_name='slug',
  251. label=_('Location (slug)'),
  252. )
  253. status = django_filters.MultipleChoiceFilter(
  254. choices=LocationStatusChoices,
  255. null_value=None
  256. )
  257. class Meta:
  258. model = Location
  259. fields = ('id', 'name', 'slug', 'facility', 'description')
  260. def search(self, queryset, name, value):
  261. if not value.strip():
  262. return queryset
  263. return queryset.filter(
  264. Q(name__icontains=value) |
  265. Q(facility__icontains=value) |
  266. Q(description__icontains=value)
  267. )
  268. class RackRoleFilterSet(OrganizationalModelFilterSet):
  269. class Meta:
  270. model = RackRole
  271. fields = ('id', 'name', 'slug', 'color', 'description')
  272. class RackTypeFilterSet(NetBoxModelFilterSet):
  273. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  274. queryset=Manufacturer.objects.all(),
  275. label=_('Manufacturer (ID)'),
  276. )
  277. manufacturer = django_filters.ModelMultipleChoiceFilter(
  278. field_name='manufacturer__slug',
  279. queryset=Manufacturer.objects.all(),
  280. to_field_name='slug',
  281. label=_('Manufacturer (slug)'),
  282. )
  283. form_factor = django_filters.MultipleChoiceFilter(
  284. choices=RackFormFactorChoices
  285. )
  286. width = django_filters.MultipleChoiceFilter(
  287. choices=RackWidthChoices
  288. )
  289. class Meta:
  290. model = RackType
  291. fields = (
  292. 'id', 'model', 'slug', 'u_height', 'starting_unit', 'desc_units', 'outer_width', 'outer_depth', 'outer_unit',
  293. 'mounting_depth', 'weight', 'max_weight', 'weight_unit', 'description',
  294. )
  295. def search(self, queryset, name, value):
  296. if not value.strip():
  297. return queryset
  298. return queryset.filter(
  299. Q(model__icontains=value) |
  300. Q(description__icontains=value) |
  301. Q(comments__icontains=value)
  302. )
  303. class RackFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilterSet):
  304. region_id = TreeNodeMultipleChoiceFilter(
  305. queryset=Region.objects.all(),
  306. field_name='site__region',
  307. lookup_expr='in',
  308. label=_('Region (ID)'),
  309. )
  310. region = TreeNodeMultipleChoiceFilter(
  311. queryset=Region.objects.all(),
  312. field_name='site__region',
  313. lookup_expr='in',
  314. to_field_name='slug',
  315. label=_('Region (slug)'),
  316. )
  317. site_group_id = TreeNodeMultipleChoiceFilter(
  318. queryset=SiteGroup.objects.all(),
  319. field_name='site__group',
  320. lookup_expr='in',
  321. label=_('Site group (ID)'),
  322. )
  323. site_group = TreeNodeMultipleChoiceFilter(
  324. queryset=SiteGroup.objects.all(),
  325. field_name='site__group',
  326. lookup_expr='in',
  327. to_field_name='slug',
  328. label=_('Site group (slug)'),
  329. )
  330. site_id = django_filters.ModelMultipleChoiceFilter(
  331. queryset=Site.objects.all(),
  332. label=_('Site (ID)'),
  333. )
  334. site = django_filters.ModelMultipleChoiceFilter(
  335. field_name='site__slug',
  336. queryset=Site.objects.all(),
  337. to_field_name='slug',
  338. label=_('Site (slug)'),
  339. )
  340. location_id = TreeNodeMultipleChoiceFilter(
  341. queryset=Location.objects.all(),
  342. field_name='location',
  343. lookup_expr='in',
  344. label=_('Location (ID)'),
  345. )
  346. location = TreeNodeMultipleChoiceFilter(
  347. queryset=Location.objects.all(),
  348. field_name='location',
  349. lookup_expr='in',
  350. to_field_name='slug',
  351. label=_('Location (slug)'),
  352. )
  353. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  354. field_name='rack_type__manufacturer',
  355. queryset=Manufacturer.objects.all(),
  356. label=_('Manufacturer (ID)'),
  357. )
  358. manufacturer = django_filters.ModelMultipleChoiceFilter(
  359. field_name='rack_type__manufacturer__slug',
  360. queryset=Manufacturer.objects.all(),
  361. to_field_name='slug',
  362. label=_('Manufacturer (slug)'),
  363. )
  364. rack_type = django_filters.ModelMultipleChoiceFilter(
  365. field_name='rack_type__slug',
  366. queryset=RackType.objects.all(),
  367. to_field_name='slug',
  368. label=_('Rack type (slug)'),
  369. )
  370. rack_type_id = django_filters.ModelMultipleChoiceFilter(
  371. queryset=RackType.objects.all(),
  372. label=_('Rack type (ID)'),
  373. )
  374. status = django_filters.MultipleChoiceFilter(
  375. choices=RackStatusChoices,
  376. null_value=None
  377. )
  378. form_factor = django_filters.MultipleChoiceFilter(
  379. choices=RackFormFactorChoices
  380. )
  381. width = django_filters.MultipleChoiceFilter(
  382. choices=RackWidthChoices
  383. )
  384. role_id = django_filters.ModelMultipleChoiceFilter(
  385. queryset=RackRole.objects.all(),
  386. label=_('Role (ID)'),
  387. )
  388. role = django_filters.ModelMultipleChoiceFilter(
  389. field_name='role__slug',
  390. queryset=RackRole.objects.all(),
  391. to_field_name='slug',
  392. label=_('Role (slug)'),
  393. )
  394. serial = MultiValueCharFilter(
  395. lookup_expr='iexact'
  396. )
  397. class Meta:
  398. model = Rack
  399. fields = (
  400. 'id', 'name', 'facility_id', 'asset_tag', 'u_height', 'starting_unit', 'desc_units', 'outer_width',
  401. 'outer_depth', 'outer_unit', 'mounting_depth', 'airflow', 'weight', 'max_weight', 'weight_unit',
  402. 'description',
  403. )
  404. def search(self, queryset, name, value):
  405. if not value.strip():
  406. return queryset
  407. return queryset.filter(
  408. Q(name__icontains=value) |
  409. Q(facility_id__icontains=value) |
  410. Q(serial__icontains=value.strip()) |
  411. Q(asset_tag__icontains=value.strip()) |
  412. Q(description__icontains=value) |
  413. Q(comments__icontains=value)
  414. )
  415. class RackReservationFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
  416. rack_id = django_filters.ModelMultipleChoiceFilter(
  417. queryset=Rack.objects.all(),
  418. label=_('Rack (ID)'),
  419. )
  420. site_id = django_filters.ModelMultipleChoiceFilter(
  421. field_name='rack__site',
  422. queryset=Site.objects.all(),
  423. label=_('Site (ID)'),
  424. )
  425. site = django_filters.ModelMultipleChoiceFilter(
  426. field_name='rack__site__slug',
  427. queryset=Site.objects.all(),
  428. to_field_name='slug',
  429. label=_('Site (slug)'),
  430. )
  431. region_id = TreeNodeMultipleChoiceFilter(
  432. queryset=Region.objects.all(),
  433. field_name='rack__site__region',
  434. lookup_expr='in',
  435. label=_('Region (ID)'),
  436. )
  437. region = TreeNodeMultipleChoiceFilter(
  438. queryset=Region.objects.all(),
  439. field_name='rack__site__region',
  440. lookup_expr='in',
  441. to_field_name='slug',
  442. label=_('Region (slug)'),
  443. )
  444. site_group_id = TreeNodeMultipleChoiceFilter(
  445. queryset=SiteGroup.objects.all(),
  446. field_name='rack__site__group',
  447. lookup_expr='in',
  448. label=_('Site group (ID)'),
  449. )
  450. site_group = TreeNodeMultipleChoiceFilter(
  451. queryset=SiteGroup.objects.all(),
  452. field_name='rack__site__group',
  453. lookup_expr='in',
  454. to_field_name='slug',
  455. label=_('Site group (slug)'),
  456. )
  457. location_id = TreeNodeMultipleChoiceFilter(
  458. queryset=Location.objects.all(),
  459. field_name='rack__location',
  460. lookup_expr='in',
  461. label=_('Location (ID)'),
  462. )
  463. location = TreeNodeMultipleChoiceFilter(
  464. queryset=Location.objects.all(),
  465. field_name='rack__location',
  466. lookup_expr='in',
  467. to_field_name='slug',
  468. label=_('Location (slug)'),
  469. )
  470. user_id = django_filters.ModelMultipleChoiceFilter(
  471. queryset=User.objects.all(),
  472. label=_('User (ID)'),
  473. )
  474. user = django_filters.ModelMultipleChoiceFilter(
  475. field_name='user__username',
  476. queryset=User.objects.all(),
  477. to_field_name='username',
  478. label=_('User (name)'),
  479. )
  480. unit = NumericArrayFilter(
  481. field_name='units',
  482. lookup_expr='contains'
  483. )
  484. class Meta:
  485. model = RackReservation
  486. fields = ('id', 'created', 'description')
  487. def search(self, queryset, name, value):
  488. if not value.strip():
  489. return queryset
  490. return queryset.filter(
  491. Q(rack__name__icontains=value) |
  492. Q(rack__facility_id__icontains=value) |
  493. Q(user__username__icontains=value) |
  494. Q(description__icontains=value)
  495. )
  496. class ManufacturerFilterSet(OrganizationalModelFilterSet, ContactModelFilterSet):
  497. class Meta:
  498. model = Manufacturer
  499. fields = ('id', 'name', 'slug', 'description')
  500. class DeviceTypeFilterSet(NetBoxModelFilterSet):
  501. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  502. queryset=Manufacturer.objects.all(),
  503. label=_('Manufacturer (ID)'),
  504. )
  505. manufacturer = django_filters.ModelMultipleChoiceFilter(
  506. field_name='manufacturer__slug',
  507. queryset=Manufacturer.objects.all(),
  508. to_field_name='slug',
  509. label=_('Manufacturer (slug)'),
  510. )
  511. default_platform_id = django_filters.ModelMultipleChoiceFilter(
  512. queryset=Platform.objects.all(),
  513. label=_('Default platform (ID)'),
  514. )
  515. default_platform = django_filters.ModelMultipleChoiceFilter(
  516. field_name='default_platform__slug',
  517. queryset=Platform.objects.all(),
  518. to_field_name='slug',
  519. label=_('Default platform (slug)'),
  520. )
  521. has_front_image = django_filters.BooleanFilter(
  522. label=_('Has a front image'),
  523. method='_has_front_image'
  524. )
  525. has_rear_image = django_filters.BooleanFilter(
  526. label=_('Has a rear image'),
  527. method='_has_rear_image'
  528. )
  529. console_ports = django_filters.BooleanFilter(
  530. method='_console_ports',
  531. label=_('Has console ports'),
  532. )
  533. console_server_ports = django_filters.BooleanFilter(
  534. method='_console_server_ports',
  535. label=_('Has console server ports'),
  536. )
  537. power_ports = django_filters.BooleanFilter(
  538. method='_power_ports',
  539. label=_('Has power ports'),
  540. )
  541. power_outlets = django_filters.BooleanFilter(
  542. method='_power_outlets',
  543. label=_('Has power outlets'),
  544. )
  545. interfaces = django_filters.BooleanFilter(
  546. method='_interfaces',
  547. label=_('Has interfaces'),
  548. )
  549. pass_through_ports = django_filters.BooleanFilter(
  550. method='_pass_through_ports',
  551. label=_('Has pass-through ports'),
  552. )
  553. module_bays = django_filters.BooleanFilter(
  554. method='_module_bays',
  555. label=_('Has module bays'),
  556. )
  557. device_bays = django_filters.BooleanFilter(
  558. method='_device_bays',
  559. label=_('Has device bays'),
  560. )
  561. inventory_items = django_filters.BooleanFilter(
  562. method='_inventory_items',
  563. label=_('Has inventory items'),
  564. )
  565. class Meta:
  566. model = DeviceType
  567. fields = (
  568. 'id', 'model', 'slug', 'part_number', 'u_height', 'exclude_from_utilization', 'is_full_depth',
  569. 'subdevice_role', 'airflow', 'weight', 'weight_unit', 'description',
  570. # Counters
  571. 'console_port_template_count',
  572. 'console_server_port_template_count',
  573. 'power_port_template_count',
  574. 'power_outlet_template_count',
  575. 'interface_template_count',
  576. 'front_port_template_count',
  577. 'rear_port_template_count',
  578. 'device_bay_template_count',
  579. 'module_bay_template_count',
  580. 'inventory_item_template_count',
  581. )
  582. def search(self, queryset, name, value):
  583. if not value.strip():
  584. return queryset
  585. return queryset.filter(
  586. Q(manufacturer__name__icontains=value) |
  587. Q(model__icontains=value) |
  588. Q(part_number__icontains=value) |
  589. Q(description__icontains=value) |
  590. Q(comments__icontains=value)
  591. )
  592. def _has_front_image(self, queryset, name, value):
  593. if value:
  594. return queryset.exclude(front_image='')
  595. else:
  596. return queryset.filter(front_image='')
  597. def _has_rear_image(self, queryset, name, value):
  598. if value:
  599. return queryset.exclude(rear_image='')
  600. else:
  601. return queryset.filter(rear_image='')
  602. def _console_ports(self, queryset, name, value):
  603. return queryset.exclude(consoleporttemplates__isnull=value)
  604. def _console_server_ports(self, queryset, name, value):
  605. return queryset.exclude(consoleserverporttemplates__isnull=value)
  606. def _power_ports(self, queryset, name, value):
  607. return queryset.exclude(powerporttemplates__isnull=value)
  608. def _power_outlets(self, queryset, name, value):
  609. return queryset.exclude(poweroutlettemplates__isnull=value)
  610. def _interfaces(self, queryset, name, value):
  611. return queryset.exclude(interfacetemplates__isnull=value)
  612. def _pass_through_ports(self, queryset, name, value):
  613. return queryset.exclude(
  614. frontporttemplates__isnull=value,
  615. rearporttemplates__isnull=value
  616. )
  617. def _module_bays(self, queryset, name, value):
  618. return queryset.exclude(modulebaytemplates__isnull=value)
  619. def _device_bays(self, queryset, name, value):
  620. return queryset.exclude(devicebaytemplates__isnull=value)
  621. def _inventory_items(self, queryset, name, value):
  622. return queryset.exclude(inventoryitemtemplates__isnull=value)
  623. class ModuleTypeFilterSet(NetBoxModelFilterSet):
  624. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  625. queryset=Manufacturer.objects.all(),
  626. label=_('Manufacturer (ID)'),
  627. )
  628. manufacturer = django_filters.ModelMultipleChoiceFilter(
  629. field_name='manufacturer__slug',
  630. queryset=Manufacturer.objects.all(),
  631. to_field_name='slug',
  632. label=_('Manufacturer (slug)'),
  633. )
  634. console_ports = django_filters.BooleanFilter(
  635. method='_console_ports',
  636. label=_('Has console ports'),
  637. )
  638. console_server_ports = django_filters.BooleanFilter(
  639. method='_console_server_ports',
  640. label=_('Has console server ports'),
  641. )
  642. power_ports = django_filters.BooleanFilter(
  643. method='_power_ports',
  644. label=_('Has power ports'),
  645. )
  646. power_outlets = django_filters.BooleanFilter(
  647. method='_power_outlets',
  648. label=_('Has power outlets'),
  649. )
  650. interfaces = django_filters.BooleanFilter(
  651. method='_interfaces',
  652. label=_('Has interfaces'),
  653. )
  654. pass_through_ports = django_filters.BooleanFilter(
  655. method='_pass_through_ports',
  656. label=_('Has pass-through ports'),
  657. )
  658. class Meta:
  659. model = ModuleType
  660. fields = ('id', 'model', 'part_number', 'airflow', 'weight', 'weight_unit', 'description')
  661. def search(self, queryset, name, value):
  662. if not value.strip():
  663. return queryset
  664. return queryset.filter(
  665. Q(manufacturer__name__icontains=value) |
  666. Q(model__icontains=value) |
  667. Q(part_number__icontains=value) |
  668. Q(description__icontains=value) |
  669. Q(comments__icontains=value)
  670. )
  671. def _console_ports(self, queryset, name, value):
  672. return queryset.exclude(consoleporttemplates__isnull=value)
  673. def _console_server_ports(self, queryset, name, value):
  674. return queryset.exclude(consoleserverporttemplates__isnull=value)
  675. def _power_ports(self, queryset, name, value):
  676. return queryset.exclude(powerporttemplates__isnull=value)
  677. def _power_outlets(self, queryset, name, value):
  678. return queryset.exclude(poweroutlettemplates__isnull=value)
  679. def _interfaces(self, queryset, name, value):
  680. return queryset.exclude(interfacetemplates__isnull=value)
  681. def _pass_through_ports(self, queryset, name, value):
  682. return queryset.exclude(
  683. frontporttemplates__isnull=value,
  684. rearporttemplates__isnull=value
  685. )
  686. class DeviceTypeComponentFilterSet(django_filters.FilterSet):
  687. q = django_filters.CharFilter(
  688. method='search',
  689. label=_('Search'),
  690. )
  691. device_type_id = django_filters.ModelMultipleChoiceFilter(
  692. queryset=DeviceType.objects.all(),
  693. field_name='device_type_id',
  694. label=_('Device type (ID)'),
  695. )
  696. def search(self, queryset, name, value):
  697. if not value.strip():
  698. return queryset
  699. return queryset.filter(
  700. Q(name__icontains=value) |
  701. Q(description__icontains=value)
  702. )
  703. class ModularDeviceTypeComponentFilterSet(DeviceTypeComponentFilterSet):
  704. module_type_id = django_filters.ModelMultipleChoiceFilter(
  705. queryset=ModuleType.objects.all(),
  706. field_name='module_type_id',
  707. label=_('Module type (ID)'),
  708. )
  709. class ConsolePortTemplateFilterSet(ChangeLoggedModelFilterSet, ModularDeviceTypeComponentFilterSet):
  710. class Meta:
  711. model = ConsolePortTemplate
  712. fields = ('id', 'name', 'label', 'type', 'description')
  713. class ConsoleServerPortTemplateFilterSet(ChangeLoggedModelFilterSet, ModularDeviceTypeComponentFilterSet):
  714. class Meta:
  715. model = ConsoleServerPortTemplate
  716. fields = ('id', 'name', 'label', 'type', 'description')
  717. class PowerPortTemplateFilterSet(ChangeLoggedModelFilterSet, ModularDeviceTypeComponentFilterSet):
  718. class Meta:
  719. model = PowerPortTemplate
  720. fields = ('id', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description')
  721. class PowerOutletTemplateFilterSet(ChangeLoggedModelFilterSet, ModularDeviceTypeComponentFilterSet):
  722. feed_leg = django_filters.MultipleChoiceFilter(
  723. choices=PowerOutletFeedLegChoices,
  724. null_value=None
  725. )
  726. power_port_id = django_filters.ModelMultipleChoiceFilter(
  727. queryset=PowerPortTemplate.objects.all(),
  728. label=_('Power port (ID)'),
  729. )
  730. class Meta:
  731. model = PowerOutletTemplate
  732. fields = ('id', 'name', 'label', 'type', 'feed_leg', 'description')
  733. class InterfaceTemplateFilterSet(ChangeLoggedModelFilterSet, ModularDeviceTypeComponentFilterSet):
  734. type = django_filters.MultipleChoiceFilter(
  735. choices=InterfaceTypeChoices,
  736. null_value=None
  737. )
  738. bridge_id = django_filters.ModelMultipleChoiceFilter(
  739. field_name='bridge',
  740. queryset=InterfaceTemplate.objects.all()
  741. )
  742. poe_mode = django_filters.MultipleChoiceFilter(
  743. choices=InterfacePoEModeChoices
  744. )
  745. poe_type = django_filters.MultipleChoiceFilter(
  746. choices=InterfacePoETypeChoices
  747. )
  748. rf_role = django_filters.MultipleChoiceFilter(
  749. choices=WirelessRoleChoices
  750. )
  751. class Meta:
  752. model = InterfaceTemplate
  753. fields = ('id', 'name', 'label', 'type', 'enabled', 'mgmt_only', 'description')
  754. class FrontPortTemplateFilterSet(ChangeLoggedModelFilterSet, ModularDeviceTypeComponentFilterSet):
  755. type = django_filters.MultipleChoiceFilter(
  756. choices=PortTypeChoices,
  757. null_value=None
  758. )
  759. rear_port_id = django_filters.ModelMultipleChoiceFilter(
  760. queryset=RearPort.objects.all()
  761. )
  762. class Meta:
  763. model = FrontPortTemplate
  764. fields = ('id', 'name', 'label', 'type', 'color', 'rear_port_position', 'description')
  765. class RearPortTemplateFilterSet(ChangeLoggedModelFilterSet, ModularDeviceTypeComponentFilterSet):
  766. type = django_filters.MultipleChoiceFilter(
  767. choices=PortTypeChoices,
  768. null_value=None
  769. )
  770. class Meta:
  771. model = RearPortTemplate
  772. fields = ('id', 'name', 'label', 'type', 'color', 'positions', 'description')
  773. class ModuleBayTemplateFilterSet(ChangeLoggedModelFilterSet, ModularDeviceTypeComponentFilterSet):
  774. class Meta:
  775. model = ModuleBayTemplate
  776. fields = ('id', 'name', 'label', 'position', 'description')
  777. class DeviceBayTemplateFilterSet(ChangeLoggedModelFilterSet, DeviceTypeComponentFilterSet):
  778. class Meta:
  779. model = DeviceBayTemplate
  780. fields = ('id', 'name', 'label', 'description')
  781. class InventoryItemTemplateFilterSet(ChangeLoggedModelFilterSet, DeviceTypeComponentFilterSet):
  782. parent_id = django_filters.ModelMultipleChoiceFilter(
  783. queryset=InventoryItemTemplate.objects.all(),
  784. label=_('Parent inventory item (ID)'),
  785. )
  786. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  787. queryset=Manufacturer.objects.all(),
  788. label=_('Manufacturer (ID)'),
  789. )
  790. manufacturer = django_filters.ModelMultipleChoiceFilter(
  791. field_name='manufacturer__slug',
  792. queryset=Manufacturer.objects.all(),
  793. to_field_name='slug',
  794. label=_('Manufacturer (slug)'),
  795. )
  796. role_id = django_filters.ModelMultipleChoiceFilter(
  797. queryset=InventoryItemRole.objects.all(),
  798. label=_('Role (ID)'),
  799. )
  800. role = django_filters.ModelMultipleChoiceFilter(
  801. field_name='role__slug',
  802. queryset=InventoryItemRole.objects.all(),
  803. to_field_name='slug',
  804. label=_('Role (slug)'),
  805. )
  806. component_type = ContentTypeFilter()
  807. component_id = MultiValueNumberFilter()
  808. class Meta:
  809. model = InventoryItemTemplate
  810. fields = ('id', 'name', 'label', 'part_id', 'description')
  811. def search(self, queryset, name, value):
  812. if not value.strip():
  813. return queryset
  814. qs_filter = (
  815. Q(name__icontains=value) |
  816. Q(part_id__icontains=value) |
  817. Q(description__icontains=value)
  818. )
  819. return queryset.filter(qs_filter)
  820. class DeviceRoleFilterSet(OrganizationalModelFilterSet):
  821. config_template_id = django_filters.ModelMultipleChoiceFilter(
  822. queryset=ConfigTemplate.objects.all(),
  823. label=_('Config template (ID)'),
  824. )
  825. class Meta:
  826. model = DeviceRole
  827. fields = ('id', 'name', 'slug', 'color', 'vm_role', 'description')
  828. class PlatformFilterSet(OrganizationalModelFilterSet):
  829. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  830. field_name='manufacturer',
  831. queryset=Manufacturer.objects.all(),
  832. label=_('Manufacturer (ID)'),
  833. )
  834. manufacturer = django_filters.ModelMultipleChoiceFilter(
  835. field_name='manufacturer__slug',
  836. queryset=Manufacturer.objects.all(),
  837. to_field_name='slug',
  838. label=_('Manufacturer (slug)'),
  839. )
  840. available_for_device_type = django_filters.ModelChoiceFilter(
  841. queryset=DeviceType.objects.all(),
  842. method='get_for_device_type'
  843. )
  844. config_template_id = django_filters.ModelMultipleChoiceFilter(
  845. queryset=ConfigTemplate.objects.all(),
  846. label=_('Config template (ID)'),
  847. )
  848. class Meta:
  849. model = Platform
  850. fields = ('id', 'name', 'slug', 'description')
  851. @extend_schema_field(OpenApiTypes.STR)
  852. def get_for_device_type(self, queryset, name, value):
  853. """
  854. Return all Platforms available for a specific manufacturer based on device type and Platforms not assigned any
  855. manufacturer
  856. """
  857. return queryset.filter(Q(manufacturer=None) | Q(manufacturer__device_types=value))
  858. class DeviceFilterSet(
  859. NetBoxModelFilterSet,
  860. TenancyFilterSet,
  861. ContactModelFilterSet,
  862. LocalConfigContextFilterSet,
  863. PrimaryIPFilterSet,
  864. ):
  865. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  866. field_name='device_type__manufacturer',
  867. queryset=Manufacturer.objects.all(),
  868. label=_('Manufacturer (ID)'),
  869. )
  870. manufacturer = django_filters.ModelMultipleChoiceFilter(
  871. field_name='device_type__manufacturer__slug',
  872. queryset=Manufacturer.objects.all(),
  873. to_field_name='slug',
  874. label=_('Manufacturer (slug)'),
  875. )
  876. device_type = django_filters.ModelMultipleChoiceFilter(
  877. field_name='device_type__slug',
  878. queryset=DeviceType.objects.all(),
  879. to_field_name='slug',
  880. label=_('Device type (slug)'),
  881. )
  882. device_type_id = django_filters.ModelMultipleChoiceFilter(
  883. queryset=DeviceType.objects.all(),
  884. label=_('Device type (ID)'),
  885. )
  886. role_id = django_filters.ModelMultipleChoiceFilter(
  887. field_name='role_id',
  888. queryset=DeviceRole.objects.all(),
  889. label=_('Role (ID)'),
  890. )
  891. role = django_filters.ModelMultipleChoiceFilter(
  892. field_name='role__slug',
  893. queryset=DeviceRole.objects.all(),
  894. to_field_name='slug',
  895. label=_('Role (slug)'),
  896. )
  897. parent_device_id = django_filters.ModelMultipleChoiceFilter(
  898. field_name='parent_bay__device',
  899. queryset=Device.objects.all(),
  900. label=_('Parent Device (ID)'),
  901. )
  902. platform_id = django_filters.ModelMultipleChoiceFilter(
  903. queryset=Platform.objects.all(),
  904. label=_('Platform (ID)'),
  905. )
  906. platform = django_filters.ModelMultipleChoiceFilter(
  907. field_name='platform__slug',
  908. queryset=Platform.objects.all(),
  909. to_field_name='slug',
  910. label=_('Platform (slug)'),
  911. )
  912. region_id = TreeNodeMultipleChoiceFilter(
  913. queryset=Region.objects.all(),
  914. field_name='site__region',
  915. lookup_expr='in',
  916. label=_('Region (ID)'),
  917. )
  918. region = TreeNodeMultipleChoiceFilter(
  919. queryset=Region.objects.all(),
  920. field_name='site__region',
  921. lookup_expr='in',
  922. to_field_name='slug',
  923. label=_('Region (slug)'),
  924. )
  925. site_group_id = TreeNodeMultipleChoiceFilter(
  926. queryset=SiteGroup.objects.all(),
  927. field_name='site__group',
  928. lookup_expr='in',
  929. label=_('Site group (ID)'),
  930. )
  931. site_group = TreeNodeMultipleChoiceFilter(
  932. queryset=SiteGroup.objects.all(),
  933. field_name='site__group',
  934. lookup_expr='in',
  935. to_field_name='slug',
  936. label=_('Site group (slug)'),
  937. )
  938. site_id = django_filters.ModelMultipleChoiceFilter(
  939. queryset=Site.objects.all(),
  940. label=_('Site (ID)'),
  941. )
  942. site = django_filters.ModelMultipleChoiceFilter(
  943. field_name='site__slug',
  944. queryset=Site.objects.all(),
  945. to_field_name='slug',
  946. label=_('Site name (slug)'),
  947. )
  948. location_id = TreeNodeMultipleChoiceFilter(
  949. queryset=Location.objects.all(),
  950. field_name='location',
  951. lookup_expr='in',
  952. label=_('Location (ID)'),
  953. )
  954. rack_id = django_filters.ModelMultipleChoiceFilter(
  955. field_name='rack',
  956. queryset=Rack.objects.all(),
  957. label=_('Rack (ID)'),
  958. )
  959. parent_bay_id = django_filters.ModelMultipleChoiceFilter(
  960. field_name='parent_bay',
  961. queryset=DeviceBay.objects.all(),
  962. label=_('Parent bay (ID)'),
  963. )
  964. cluster_id = django_filters.ModelMultipleChoiceFilter(
  965. queryset=Cluster.objects.all(),
  966. label=_('VM cluster (ID)'),
  967. )
  968. cluster_group = django_filters.ModelMultipleChoiceFilter(
  969. field_name='cluster__group__slug',
  970. queryset=ClusterGroup.objects.all(),
  971. to_field_name='slug',
  972. label=_('Cluster group (slug)'),
  973. )
  974. cluster_group_id = django_filters.ModelMultipleChoiceFilter(
  975. field_name='cluster__group',
  976. queryset=ClusterGroup.objects.all(),
  977. label=_('Cluster group (ID)'),
  978. )
  979. model = django_filters.ModelMultipleChoiceFilter(
  980. field_name='device_type__slug',
  981. queryset=DeviceType.objects.all(),
  982. to_field_name='slug',
  983. label=_('Device model (slug)'),
  984. )
  985. name = MultiValueCharFilter(
  986. lookup_expr='iexact'
  987. )
  988. status = django_filters.MultipleChoiceFilter(
  989. choices=DeviceStatusChoices,
  990. null_value=None
  991. )
  992. is_full_depth = django_filters.BooleanFilter(
  993. field_name='device_type__is_full_depth',
  994. label=_('Is full depth'),
  995. )
  996. mac_address = MultiValueMACAddressFilter(
  997. field_name='interfaces__mac_address',
  998. label=_('MAC address'),
  999. )
  1000. serial = MultiValueCharFilter(
  1001. lookup_expr='iexact'
  1002. )
  1003. has_primary_ip = django_filters.BooleanFilter(
  1004. method='_has_primary_ip',
  1005. label=_('Has a primary IP'),
  1006. )
  1007. has_oob_ip = django_filters.BooleanFilter(
  1008. method='_has_oob_ip',
  1009. label=_('Has an out-of-band IP'),
  1010. )
  1011. virtual_chassis_id = django_filters.ModelMultipleChoiceFilter(
  1012. field_name='virtual_chassis',
  1013. queryset=VirtualChassis.objects.all(),
  1014. label=_('Virtual chassis (ID)'),
  1015. )
  1016. virtual_chassis_member = django_filters.BooleanFilter(
  1017. method='_virtual_chassis_member',
  1018. label=_('Is a virtual chassis member')
  1019. )
  1020. config_template_id = django_filters.ModelMultipleChoiceFilter(
  1021. queryset=ConfigTemplate.objects.all(),
  1022. label=_('Config template (ID)'),
  1023. )
  1024. console_ports = django_filters.BooleanFilter(
  1025. method='_console_ports',
  1026. label=_('Has console ports'),
  1027. )
  1028. console_server_ports = django_filters.BooleanFilter(
  1029. method='_console_server_ports',
  1030. label=_('Has console server ports'),
  1031. )
  1032. power_ports = django_filters.BooleanFilter(
  1033. method='_power_ports',
  1034. label=_('Has power ports'),
  1035. )
  1036. power_outlets = django_filters.BooleanFilter(
  1037. method='_power_outlets',
  1038. label=_('Has power outlets'),
  1039. )
  1040. interfaces = django_filters.BooleanFilter(
  1041. method='_interfaces',
  1042. label=_('Has interfaces'),
  1043. )
  1044. pass_through_ports = django_filters.BooleanFilter(
  1045. method='_pass_through_ports',
  1046. label=_('Has pass-through ports'),
  1047. )
  1048. module_bays = django_filters.BooleanFilter(
  1049. method='_module_bays',
  1050. label=_('Has module bays'),
  1051. )
  1052. device_bays = django_filters.BooleanFilter(
  1053. method='_device_bays',
  1054. label=_('Has device bays'),
  1055. )
  1056. oob_ip_id = django_filters.ModelMultipleChoiceFilter(
  1057. field_name='oob_ip',
  1058. queryset=IPAddress.objects.all(),
  1059. label=_('OOB IP (ID)'),
  1060. )
  1061. has_virtual_device_context = django_filters.BooleanFilter(
  1062. method='_has_virtual_device_context',
  1063. label=_('Has virtual device context'),
  1064. )
  1065. class Meta:
  1066. model = Device
  1067. fields = (
  1068. 'id', 'asset_tag', 'face', 'position', 'latitude', 'longitude', 'airflow', 'vc_position', 'vc_priority',
  1069. 'description',
  1070. # Counters
  1071. 'console_port_count',
  1072. 'console_server_port_count',
  1073. 'power_port_count',
  1074. 'power_outlet_count',
  1075. 'interface_count',
  1076. 'front_port_count',
  1077. 'rear_port_count',
  1078. 'device_bay_count',
  1079. 'module_bay_count',
  1080. 'inventory_item_count',
  1081. )
  1082. def search(self, queryset, name, value):
  1083. if not value.strip():
  1084. return queryset
  1085. return queryset.filter(
  1086. Q(name__icontains=value) |
  1087. Q(serial__icontains=value.strip()) |
  1088. Q(inventoryitems__serial__icontains=value.strip()) |
  1089. Q(asset_tag__icontains=value.strip()) |
  1090. Q(description__icontains=value.strip()) |
  1091. Q(comments__icontains=value) |
  1092. Q(primary_ip4__address__startswith=value) |
  1093. Q(primary_ip6__address__startswith=value)
  1094. ).distinct()
  1095. def _has_primary_ip(self, queryset, name, value):
  1096. params = Q(primary_ip4__isnull=False) | Q(primary_ip6__isnull=False)
  1097. if value:
  1098. return queryset.filter(params)
  1099. return queryset.exclude(params)
  1100. def _has_oob_ip(self, queryset, name, value):
  1101. params = Q(oob_ip__isnull=False)
  1102. if value:
  1103. return queryset.filter(params)
  1104. return queryset.exclude(params)
  1105. def _virtual_chassis_member(self, queryset, name, value):
  1106. return queryset.exclude(virtual_chassis__isnull=value)
  1107. def _console_ports(self, queryset, name, value):
  1108. return queryset.exclude(consoleports__isnull=value)
  1109. def _console_server_ports(self, queryset, name, value):
  1110. return queryset.exclude(consoleserverports__isnull=value)
  1111. def _power_ports(self, queryset, name, value):
  1112. return queryset.exclude(powerports__isnull=value)
  1113. def _power_outlets(self, queryset, name, value):
  1114. return queryset.exclude(poweroutlets__isnull=value)
  1115. def _interfaces(self, queryset, name, value):
  1116. return queryset.exclude(interfaces__isnull=value)
  1117. def _pass_through_ports(self, queryset, name, value):
  1118. return queryset.exclude(
  1119. frontports__isnull=value,
  1120. rearports__isnull=value
  1121. )
  1122. def _module_bays(self, queryset, name, value):
  1123. return queryset.exclude(modulebays__isnull=value)
  1124. def _device_bays(self, queryset, name, value):
  1125. return queryset.exclude(devicebays__isnull=value)
  1126. def _has_virtual_device_context(self, queryset, name, value):
  1127. params = Q(vdcs__isnull=False)
  1128. if value:
  1129. return queryset.filter(params).distinct()
  1130. return queryset.exclude(params)
  1131. class VirtualDeviceContextFilterSet(NetBoxModelFilterSet, TenancyFilterSet, PrimaryIPFilterSet):
  1132. device_id = django_filters.ModelMultipleChoiceFilter(
  1133. field_name='device',
  1134. queryset=Device.objects.all(),
  1135. label=_('VDC (ID)')
  1136. )
  1137. device = django_filters.ModelMultipleChoiceFilter(
  1138. field_name='device',
  1139. queryset=Device.objects.all(),
  1140. label=_('Device model')
  1141. )
  1142. interface_id = django_filters.ModelMultipleChoiceFilter(
  1143. field_name='interfaces',
  1144. queryset=Interface.objects.all(),
  1145. label=_('Interface (ID)')
  1146. )
  1147. status = django_filters.MultipleChoiceFilter(
  1148. choices=VirtualDeviceContextStatusChoices
  1149. )
  1150. has_primary_ip = django_filters.BooleanFilter(
  1151. method='_has_primary_ip',
  1152. label=_('Has a primary IP')
  1153. )
  1154. class Meta:
  1155. model = VirtualDeviceContext
  1156. fields = ('id', 'device', 'name', 'identifier', 'description')
  1157. def search(self, queryset, name, value):
  1158. if not value.strip():
  1159. return queryset
  1160. qs_filter = (
  1161. Q(name__icontains=value) |
  1162. Q(description__icontains=value)
  1163. )
  1164. try:
  1165. qs_filter |= Q(identifier=int(value))
  1166. except ValueError:
  1167. pass
  1168. return queryset.filter(qs_filter).distinct()
  1169. def _has_primary_ip(self, queryset, name, value):
  1170. params = Q(primary_ip4__isnull=False) | Q(primary_ip6__isnull=False)
  1171. if value:
  1172. return queryset.filter(params)
  1173. return queryset.exclude(params)
  1174. class ModuleFilterSet(NetBoxModelFilterSet):
  1175. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  1176. field_name='module_type__manufacturer',
  1177. queryset=Manufacturer.objects.all(),
  1178. label=_('Manufacturer (ID)'),
  1179. )
  1180. manufacturer = django_filters.ModelMultipleChoiceFilter(
  1181. field_name='module_type__manufacturer__slug',
  1182. queryset=Manufacturer.objects.all(),
  1183. to_field_name='slug',
  1184. label=_('Manufacturer (slug)'),
  1185. )
  1186. module_type_id = django_filters.ModelMultipleChoiceFilter(
  1187. field_name='module_type',
  1188. queryset=ModuleType.objects.all(),
  1189. label=_('Module type (ID)'),
  1190. )
  1191. module_type = django_filters.ModelMultipleChoiceFilter(
  1192. field_name='module_type__model',
  1193. queryset=ModuleType.objects.all(),
  1194. to_field_name='model',
  1195. label=_('Module type (model)'),
  1196. )
  1197. module_bay_id = TreeNodeMultipleChoiceFilter(
  1198. queryset=ModuleBay.objects.all(),
  1199. field_name='module_bay',
  1200. lookup_expr='in',
  1201. label=_('Module bay (ID)'),
  1202. )
  1203. device_id = django_filters.ModelMultipleChoiceFilter(
  1204. queryset=Device.objects.all(),
  1205. label=_('Device (ID)'),
  1206. )
  1207. status = django_filters.MultipleChoiceFilter(
  1208. choices=ModuleStatusChoices,
  1209. null_value=None
  1210. )
  1211. serial = MultiValueCharFilter(
  1212. lookup_expr='iexact'
  1213. )
  1214. class Meta:
  1215. model = Module
  1216. fields = ('id', 'status', 'asset_tag', 'description')
  1217. def search(self, queryset, name, value):
  1218. if not value.strip():
  1219. return queryset
  1220. return queryset.filter(
  1221. Q(device__name__icontains=value.strip()) |
  1222. Q(serial__icontains=value.strip()) |
  1223. Q(asset_tag__icontains=value.strip()) |
  1224. Q(description__icontains=value) |
  1225. Q(comments__icontains=value)
  1226. ).distinct()
  1227. class DeviceComponentFilterSet(django_filters.FilterSet):
  1228. q = django_filters.CharFilter(
  1229. method='search',
  1230. label=_('Search'),
  1231. )
  1232. region_id = TreeNodeMultipleChoiceFilter(
  1233. queryset=Region.objects.all(),
  1234. field_name='device__site__region',
  1235. lookup_expr='in',
  1236. label=_('Region (ID)'),
  1237. )
  1238. region = TreeNodeMultipleChoiceFilter(
  1239. queryset=Region.objects.all(),
  1240. field_name='device__site__region',
  1241. lookup_expr='in',
  1242. to_field_name='slug',
  1243. label=_('Region (slug)'),
  1244. )
  1245. site_group_id = TreeNodeMultipleChoiceFilter(
  1246. queryset=SiteGroup.objects.all(),
  1247. field_name='device__site__group',
  1248. lookup_expr='in',
  1249. label=_('Site group (ID)'),
  1250. )
  1251. site_group = TreeNodeMultipleChoiceFilter(
  1252. queryset=SiteGroup.objects.all(),
  1253. field_name='device__site__group',
  1254. lookup_expr='in',
  1255. to_field_name='slug',
  1256. label=_('Site group (slug)'),
  1257. )
  1258. site_id = django_filters.ModelMultipleChoiceFilter(
  1259. field_name='device__site',
  1260. queryset=Site.objects.all(),
  1261. label=_('Site (ID)'),
  1262. )
  1263. site = django_filters.ModelMultipleChoiceFilter(
  1264. field_name='device__site__slug',
  1265. queryset=Site.objects.all(),
  1266. to_field_name='slug',
  1267. label=_('Site name (slug)'),
  1268. )
  1269. location_id = django_filters.ModelMultipleChoiceFilter(
  1270. field_name='device__location',
  1271. queryset=Location.objects.all(),
  1272. label=_('Location (ID)'),
  1273. )
  1274. location = django_filters.ModelMultipleChoiceFilter(
  1275. field_name='device__location__slug',
  1276. queryset=Location.objects.all(),
  1277. to_field_name='slug',
  1278. label=_('Location (slug)'),
  1279. )
  1280. rack_id = django_filters.ModelMultipleChoiceFilter(
  1281. field_name='device__rack',
  1282. queryset=Rack.objects.all(),
  1283. label=_('Rack (ID)'),
  1284. )
  1285. rack = django_filters.ModelMultipleChoiceFilter(
  1286. field_name='device__rack__name',
  1287. queryset=Rack.objects.all(),
  1288. to_field_name='name',
  1289. label=_('Rack (name)'),
  1290. )
  1291. device_id = django_filters.ModelMultipleChoiceFilter(
  1292. queryset=Device.objects.all(),
  1293. label=_('Device (ID)'),
  1294. )
  1295. device = django_filters.ModelMultipleChoiceFilter(
  1296. field_name='device__name',
  1297. queryset=Device.objects.all(),
  1298. to_field_name='name',
  1299. label=_('Device (name)'),
  1300. )
  1301. device_type_id = django_filters.ModelMultipleChoiceFilter(
  1302. field_name='device__device_type',
  1303. queryset=DeviceType.objects.all(),
  1304. label=_('Device type (ID)'),
  1305. )
  1306. device_type = django_filters.ModelMultipleChoiceFilter(
  1307. field_name='device__device_type__model',
  1308. queryset=DeviceType.objects.all(),
  1309. to_field_name='model',
  1310. label=_('Device type (model)'),
  1311. )
  1312. device_role_id = django_filters.ModelMultipleChoiceFilter(
  1313. field_name='device__role',
  1314. queryset=DeviceRole.objects.all(),
  1315. label=_('Device role (ID)'),
  1316. )
  1317. device_role = django_filters.ModelMultipleChoiceFilter(
  1318. field_name='device__role__slug',
  1319. queryset=DeviceRole.objects.all(),
  1320. to_field_name='slug',
  1321. label=_('Device role (slug)'),
  1322. )
  1323. virtual_chassis_id = django_filters.ModelMultipleChoiceFilter(
  1324. field_name='device__virtual_chassis',
  1325. queryset=VirtualChassis.objects.all(),
  1326. label=_('Virtual Chassis (ID)')
  1327. )
  1328. virtual_chassis = django_filters.ModelMultipleChoiceFilter(
  1329. field_name='device__virtual_chassis__name',
  1330. queryset=VirtualChassis.objects.all(),
  1331. to_field_name='name',
  1332. label=_('Virtual Chassis'),
  1333. )
  1334. device_status = django_filters.MultipleChoiceFilter(
  1335. choices=DeviceStatusChoices,
  1336. field_name='device__status',
  1337. )
  1338. def search(self, queryset, name, value):
  1339. if not value.strip():
  1340. return queryset
  1341. return queryset.filter(
  1342. Q(name__icontains=value) |
  1343. Q(label__icontains=value) |
  1344. Q(description__icontains=value)
  1345. )
  1346. class ModularDeviceComponentFilterSet(DeviceComponentFilterSet):
  1347. """
  1348. Extends DeviceComponentFilterSet to add a module_id filter for components
  1349. which can be associated with a particular module within a device.
  1350. """
  1351. module_id = django_filters.ModelMultipleChoiceFilter(
  1352. queryset=Module.objects.all(),
  1353. label=_('Module (ID)'),
  1354. )
  1355. class CabledObjectFilterSet(django_filters.FilterSet):
  1356. cable_id = django_filters.ModelMultipleChoiceFilter(
  1357. queryset=Cable.objects.all(),
  1358. label=_('Cable (ID)'),
  1359. )
  1360. cabled = django_filters.BooleanFilter(
  1361. field_name='cable',
  1362. lookup_expr='isnull',
  1363. exclude=True
  1364. )
  1365. occupied = django_filters.BooleanFilter(
  1366. method='filter_occupied'
  1367. )
  1368. def filter_occupied(self, queryset, name, value):
  1369. if value:
  1370. return queryset.filter(Q(cable__isnull=False) | Q(mark_connected=True))
  1371. else:
  1372. return queryset.filter(cable__isnull=True, mark_connected=False)
  1373. class PathEndpointFilterSet(django_filters.FilterSet):
  1374. connected = django_filters.BooleanFilter(
  1375. method='filter_connected'
  1376. )
  1377. def filter_connected(self, queryset, name, value):
  1378. if value:
  1379. return queryset.filter(_path__is_active=True)
  1380. else:
  1381. return queryset.filter(Q(_path__isnull=True) | Q(_path__is_active=False))
  1382. class ConsolePortFilterSet(
  1383. ModularDeviceComponentFilterSet,
  1384. NetBoxModelFilterSet,
  1385. CabledObjectFilterSet,
  1386. PathEndpointFilterSet
  1387. ):
  1388. type = django_filters.MultipleChoiceFilter(
  1389. choices=ConsolePortTypeChoices,
  1390. null_value=None
  1391. )
  1392. class Meta:
  1393. model = ConsolePort
  1394. fields = ('id', 'name', 'label', 'speed', 'description', 'mark_connected', 'cable_end')
  1395. class ConsoleServerPortFilterSet(
  1396. ModularDeviceComponentFilterSet,
  1397. NetBoxModelFilterSet,
  1398. CabledObjectFilterSet,
  1399. PathEndpointFilterSet
  1400. ):
  1401. type = django_filters.MultipleChoiceFilter(
  1402. choices=ConsolePortTypeChoices,
  1403. null_value=None
  1404. )
  1405. class Meta:
  1406. model = ConsoleServerPort
  1407. fields = ('id', 'name', 'label', 'speed', 'description', 'mark_connected', 'cable_end')
  1408. class PowerPortFilterSet(
  1409. ModularDeviceComponentFilterSet,
  1410. NetBoxModelFilterSet,
  1411. CabledObjectFilterSet,
  1412. PathEndpointFilterSet
  1413. ):
  1414. type = django_filters.MultipleChoiceFilter(
  1415. choices=PowerPortTypeChoices,
  1416. null_value=None
  1417. )
  1418. class Meta:
  1419. model = PowerPort
  1420. fields = (
  1421. 'id', 'name', 'label', 'maximum_draw', 'allocated_draw', 'description', 'mark_connected', 'cable_end',
  1422. )
  1423. class PowerOutletFilterSet(
  1424. ModularDeviceComponentFilterSet,
  1425. NetBoxModelFilterSet,
  1426. CabledObjectFilterSet,
  1427. PathEndpointFilterSet
  1428. ):
  1429. type = django_filters.MultipleChoiceFilter(
  1430. choices=PowerOutletTypeChoices,
  1431. null_value=None
  1432. )
  1433. feed_leg = django_filters.MultipleChoiceFilter(
  1434. choices=PowerOutletFeedLegChoices,
  1435. null_value=None
  1436. )
  1437. power_port_id = django_filters.ModelMultipleChoiceFilter(
  1438. queryset=PowerPort.objects.all(),
  1439. label=_('Power port (ID)'),
  1440. )
  1441. class Meta:
  1442. model = PowerOutlet
  1443. fields = (
  1444. 'id', 'name', 'label', 'feed_leg', 'description', 'color', 'mark_connected', 'cable_end',
  1445. )
  1446. class CommonInterfaceFilterSet(django_filters.FilterSet):
  1447. vlan_id = django_filters.CharFilter(
  1448. method='filter_vlan_id',
  1449. label=_('Assigned VLAN')
  1450. )
  1451. vlan = django_filters.CharFilter(
  1452. method='filter_vlan',
  1453. label=_('Assigned VID')
  1454. )
  1455. vrf_id = django_filters.ModelMultipleChoiceFilter(
  1456. field_name='vrf',
  1457. queryset=VRF.objects.all(),
  1458. label=_('VRF'),
  1459. )
  1460. vrf = django_filters.ModelMultipleChoiceFilter(
  1461. field_name='vrf__rd',
  1462. queryset=VRF.objects.all(),
  1463. to_field_name='rd',
  1464. label=_('VRF (RD)'),
  1465. )
  1466. l2vpn_id = django_filters.ModelMultipleChoiceFilter(
  1467. field_name='l2vpn_terminations__l2vpn',
  1468. queryset=L2VPN.objects.all(),
  1469. label=_('L2VPN (ID)'),
  1470. )
  1471. l2vpn = django_filters.ModelMultipleChoiceFilter(
  1472. field_name='l2vpn_terminations__l2vpn__identifier',
  1473. queryset=L2VPN.objects.all(),
  1474. to_field_name='identifier',
  1475. label=_('L2VPN'),
  1476. )
  1477. vlan_translation_policy_id = django_filters.ModelMultipleChoiceFilter(
  1478. field_name='vlan_translation_policy',
  1479. queryset=VLANTranslationPolicy.objects.all(),
  1480. label=_('VLAN Translation Policy (ID)'),
  1481. )
  1482. vlan_translation_policy = django_filters.ModelMultipleChoiceFilter(
  1483. field_name='vlan_translation_policy__name',
  1484. queryset=VLANTranslationPolicy.objects.all(),
  1485. to_field_name='name',
  1486. label=_('VLAN Translation Policy'),
  1487. )
  1488. def filter_vlan_id(self, queryset, name, value):
  1489. value = value.strip()
  1490. if not value:
  1491. return queryset
  1492. return queryset.filter(
  1493. Q(untagged_vlan_id=value) |
  1494. Q(tagged_vlans=value)
  1495. )
  1496. def filter_vlan(self, queryset, name, value):
  1497. value = value.strip()
  1498. if not value:
  1499. return queryset
  1500. return queryset.filter(
  1501. Q(untagged_vlan_id__vid=value) |
  1502. Q(tagged_vlans__vid=value)
  1503. )
  1504. class InterfaceFilterSet(
  1505. ModularDeviceComponentFilterSet,
  1506. NetBoxModelFilterSet,
  1507. CabledObjectFilterSet,
  1508. PathEndpointFilterSet,
  1509. CommonInterfaceFilterSet
  1510. ):
  1511. virtual_chassis_member = MultiValueCharFilter(
  1512. method='filter_virtual_chassis_member',
  1513. field_name='name',
  1514. label=_('Virtual Chassis Interfaces for Device')
  1515. )
  1516. virtual_chassis_member_id = MultiValueNumberFilter(
  1517. method='filter_virtual_chassis_member',
  1518. field_name='pk',
  1519. label=_('Virtual Chassis Interfaces for Device (ID)')
  1520. )
  1521. kind = django_filters.CharFilter(
  1522. method='filter_kind',
  1523. label=_('Kind of interface'),
  1524. )
  1525. parent_id = django_filters.ModelMultipleChoiceFilter(
  1526. field_name='parent',
  1527. queryset=Interface.objects.all(),
  1528. label=_('Parent interface (ID)'),
  1529. )
  1530. bridge_id = django_filters.ModelMultipleChoiceFilter(
  1531. field_name='bridge',
  1532. queryset=Interface.objects.all(),
  1533. label=_('Bridged interface (ID)'),
  1534. )
  1535. lag_id = django_filters.ModelMultipleChoiceFilter(
  1536. field_name='lag',
  1537. queryset=Interface.objects.all(),
  1538. label=_('LAG interface (ID)'),
  1539. )
  1540. speed = MultiValueNumberFilter()
  1541. duplex = django_filters.MultipleChoiceFilter(
  1542. choices=InterfaceDuplexChoices
  1543. )
  1544. mac_address = MultiValueMACAddressFilter()
  1545. wwn = MultiValueWWNFilter()
  1546. poe_mode = django_filters.MultipleChoiceFilter(
  1547. choices=InterfacePoEModeChoices
  1548. )
  1549. poe_type = django_filters.MultipleChoiceFilter(
  1550. choices=InterfacePoETypeChoices
  1551. )
  1552. type = django_filters.MultipleChoiceFilter(
  1553. choices=InterfaceTypeChoices,
  1554. null_value=None
  1555. )
  1556. rf_role = django_filters.MultipleChoiceFilter(
  1557. choices=WirelessRoleChoices
  1558. )
  1559. rf_channel = django_filters.MultipleChoiceFilter(
  1560. choices=WirelessChannelChoices
  1561. )
  1562. vdc_id = django_filters.ModelMultipleChoiceFilter(
  1563. field_name='vdcs',
  1564. queryset=VirtualDeviceContext.objects.all(),
  1565. label=_('Virtual Device Context')
  1566. )
  1567. vdc_identifier = django_filters.ModelMultipleChoiceFilter(
  1568. field_name='vdcs__identifier',
  1569. queryset=VirtualDeviceContext.objects.all(),
  1570. to_field_name='identifier',
  1571. label=_('Virtual Device Context (Identifier)')
  1572. )
  1573. vdc = django_filters.ModelMultipleChoiceFilter(
  1574. field_name='vdcs__name',
  1575. queryset=VirtualDeviceContext.objects.all(),
  1576. to_field_name='name',
  1577. label=_('Virtual Device Context')
  1578. )
  1579. wireless_lan_id = django_filters.ModelMultipleChoiceFilter(
  1580. field_name='wireless_lans',
  1581. queryset=WirelessLAN.objects.all(),
  1582. label=_('Wireless LAN')
  1583. )
  1584. wireless_link_id = django_filters.ModelMultipleChoiceFilter(
  1585. queryset=WirelessLink.objects.all(),
  1586. label=_('Wireless link')
  1587. )
  1588. class Meta:
  1589. model = Interface
  1590. fields = (
  1591. 'id', 'name', 'label', 'type', 'enabled', 'mtu', 'mgmt_only', 'poe_mode', 'poe_type', 'mode', 'rf_role',
  1592. 'rf_channel', 'rf_channel_frequency', 'rf_channel_width', 'tx_power', 'description', 'mark_connected',
  1593. 'cable_id', 'cable_end',
  1594. )
  1595. def filter_virtual_chassis_member(self, queryset, name, value):
  1596. try:
  1597. vc_interface_ids = []
  1598. for device in Device.objects.filter(**{f'{name}__in': value}):
  1599. vc_interface_ids.extend(device.vc_interfaces(if_master=False).values_list('id', flat=True))
  1600. return queryset.filter(pk__in=vc_interface_ids)
  1601. except Device.DoesNotExist:
  1602. return queryset.none()
  1603. def filter_kind(self, queryset, name, value):
  1604. value = value.strip().lower()
  1605. return {
  1606. 'physical': queryset.exclude(type__in=NONCONNECTABLE_IFACE_TYPES),
  1607. 'virtual': queryset.filter(type__in=VIRTUAL_IFACE_TYPES),
  1608. 'wireless': queryset.filter(type__in=WIRELESS_IFACE_TYPES),
  1609. }.get(value, queryset.none())
  1610. class FrontPortFilterSet(
  1611. ModularDeviceComponentFilterSet,
  1612. NetBoxModelFilterSet,
  1613. CabledObjectFilterSet
  1614. ):
  1615. type = django_filters.MultipleChoiceFilter(
  1616. choices=PortTypeChoices,
  1617. null_value=None
  1618. )
  1619. rear_port_id = django_filters.ModelMultipleChoiceFilter(
  1620. queryset=RearPort.objects.all()
  1621. )
  1622. class Meta:
  1623. model = FrontPort
  1624. fields = (
  1625. 'id', 'name', 'label', 'type', 'color', 'rear_port_position', 'description', 'mark_connected', 'cable_end',
  1626. )
  1627. class RearPortFilterSet(
  1628. ModularDeviceComponentFilterSet,
  1629. NetBoxModelFilterSet,
  1630. CabledObjectFilterSet
  1631. ):
  1632. type = django_filters.MultipleChoiceFilter(
  1633. choices=PortTypeChoices,
  1634. null_value=None
  1635. )
  1636. class Meta:
  1637. model = RearPort
  1638. fields = (
  1639. 'id', 'name', 'label', 'type', 'color', 'positions', 'description', 'mark_connected', 'cable_end',
  1640. )
  1641. class ModuleBayFilterSet(ModularDeviceComponentFilterSet, NetBoxModelFilterSet):
  1642. parent_id = django_filters.ModelMultipleChoiceFilter(
  1643. queryset=ModuleBay.objects.all(),
  1644. label=_('Parent module bay (ID)'),
  1645. )
  1646. installed_module_id = django_filters.ModelMultipleChoiceFilter(
  1647. field_name='installed_module',
  1648. queryset=ModuleBay.objects.all(),
  1649. label=_('Installed module (ID)'),
  1650. )
  1651. class Meta:
  1652. model = ModuleBay
  1653. fields = ('id', 'name', 'label', 'position', 'description')
  1654. class DeviceBayFilterSet(DeviceComponentFilterSet, NetBoxModelFilterSet):
  1655. installed_device_id = django_filters.ModelMultipleChoiceFilter(
  1656. queryset=Device.objects.all(),
  1657. label=_('Installed device (ID)'),
  1658. )
  1659. installed_device = django_filters.ModelMultipleChoiceFilter(
  1660. field_name='installed_device__name',
  1661. queryset=Device.objects.all(),
  1662. to_field_name='name',
  1663. label=_('Installed device (name)'),
  1664. )
  1665. class Meta:
  1666. model = DeviceBay
  1667. fields = ('id', 'name', 'label', 'description')
  1668. class InventoryItemFilterSet(DeviceComponentFilterSet, NetBoxModelFilterSet):
  1669. parent_id = django_filters.ModelMultipleChoiceFilter(
  1670. queryset=InventoryItem.objects.all(),
  1671. label=_('Parent inventory item (ID)'),
  1672. )
  1673. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  1674. queryset=Manufacturer.objects.all(),
  1675. label=_('Manufacturer (ID)'),
  1676. )
  1677. manufacturer = django_filters.ModelMultipleChoiceFilter(
  1678. field_name='manufacturer__slug',
  1679. queryset=Manufacturer.objects.all(),
  1680. to_field_name='slug',
  1681. label=_('Manufacturer (slug)'),
  1682. )
  1683. role_id = django_filters.ModelMultipleChoiceFilter(
  1684. queryset=InventoryItemRole.objects.all(),
  1685. label=_('Role (ID)'),
  1686. )
  1687. role = django_filters.ModelMultipleChoiceFilter(
  1688. field_name='role__slug',
  1689. queryset=InventoryItemRole.objects.all(),
  1690. to_field_name='slug',
  1691. label=_('Role (slug)'),
  1692. )
  1693. component_type = ContentTypeFilter()
  1694. component_id = MultiValueNumberFilter()
  1695. serial = MultiValueCharFilter(
  1696. lookup_expr='iexact'
  1697. )
  1698. status = django_filters.MultipleChoiceFilter(
  1699. choices=InventoryItemStatusChoices,
  1700. null_value=None
  1701. )
  1702. class Meta:
  1703. model = InventoryItem
  1704. fields = ('id', 'name', 'label', 'part_id', 'asset_tag', 'status', 'description', 'discovered')
  1705. def search(self, queryset, name, value):
  1706. if not value.strip():
  1707. return queryset
  1708. qs_filter = (
  1709. Q(name__icontains=value) |
  1710. Q(part_id__icontains=value) |
  1711. Q(serial__icontains=value) |
  1712. Q(asset_tag__icontains=value) |
  1713. Q(description__icontains=value)
  1714. )
  1715. return queryset.filter(qs_filter)
  1716. class InventoryItemRoleFilterSet(OrganizationalModelFilterSet):
  1717. class Meta:
  1718. model = InventoryItemRole
  1719. fields = ('id', 'name', 'slug', 'color', 'description')
  1720. class VirtualChassisFilterSet(NetBoxModelFilterSet):
  1721. master_id = django_filters.ModelMultipleChoiceFilter(
  1722. queryset=Device.objects.all(),
  1723. label=_('Master (ID)'),
  1724. )
  1725. master = django_filters.ModelMultipleChoiceFilter(
  1726. field_name='master__name',
  1727. queryset=Device.objects.all(),
  1728. to_field_name='name',
  1729. label=_('Master (name)'),
  1730. )
  1731. region_id = TreeNodeMultipleChoiceFilter(
  1732. queryset=Region.objects.all(),
  1733. field_name='master__site__region',
  1734. lookup_expr='in',
  1735. label=_('Region (ID)'),
  1736. )
  1737. region = TreeNodeMultipleChoiceFilter(
  1738. queryset=Region.objects.all(),
  1739. field_name='master__site__region',
  1740. lookup_expr='in',
  1741. to_field_name='slug',
  1742. label=_('Region (slug)'),
  1743. )
  1744. site_group_id = TreeNodeMultipleChoiceFilter(
  1745. queryset=SiteGroup.objects.all(),
  1746. field_name='master__site__group',
  1747. lookup_expr='in',
  1748. label=_('Site group (ID)'),
  1749. )
  1750. site_group = TreeNodeMultipleChoiceFilter(
  1751. queryset=SiteGroup.objects.all(),
  1752. field_name='master__site__group',
  1753. lookup_expr='in',
  1754. to_field_name='slug',
  1755. label=_('Site group (slug)'),
  1756. )
  1757. site_id = django_filters.ModelMultipleChoiceFilter(
  1758. field_name='master__site',
  1759. queryset=Site.objects.all(),
  1760. label=_('Site (ID)'),
  1761. )
  1762. site = django_filters.ModelMultipleChoiceFilter(
  1763. field_name='master__site__slug',
  1764. queryset=Site.objects.all(),
  1765. to_field_name='slug',
  1766. label=_('Site name (slug)'),
  1767. )
  1768. tenant_id = django_filters.ModelMultipleChoiceFilter(
  1769. field_name='master__tenant',
  1770. queryset=Tenant.objects.all(),
  1771. label=_('Tenant (ID)'),
  1772. )
  1773. tenant = django_filters.ModelMultipleChoiceFilter(
  1774. field_name='master__tenant__slug',
  1775. queryset=Tenant.objects.all(),
  1776. to_field_name='slug',
  1777. label=_('Tenant (slug)'),
  1778. )
  1779. class Meta:
  1780. model = VirtualChassis
  1781. fields = ('id', 'domain', 'name', 'description', 'member_count')
  1782. def search(self, queryset, name, value):
  1783. if not value.strip():
  1784. return queryset
  1785. qs_filter = (
  1786. Q(name__icontains=value) |
  1787. Q(description__icontains=value) |
  1788. Q(members__name__icontains=value) |
  1789. Q(domain__icontains=value)
  1790. )
  1791. return queryset.filter(qs_filter).distinct()
  1792. class CableFilterSet(TenancyFilterSet, NetBoxModelFilterSet):
  1793. termination_a_type = ContentTypeFilter(
  1794. field_name='terminations__termination_type'
  1795. )
  1796. termination_a_id = MultiValueNumberFilter(
  1797. method='filter_by_cable_end_a',
  1798. field_name='terminations__termination_id'
  1799. )
  1800. termination_b_type = ContentTypeFilter(
  1801. field_name='terminations__termination_type'
  1802. )
  1803. termination_b_id = MultiValueNumberFilter(
  1804. method='filter_by_cable_end_b',
  1805. field_name='terminations__termination_id'
  1806. )
  1807. unterminated = django_filters.BooleanFilter(
  1808. method='_unterminated',
  1809. label=_('Unterminated'),
  1810. )
  1811. type = django_filters.MultipleChoiceFilter(
  1812. choices=CableTypeChoices
  1813. )
  1814. status = django_filters.MultipleChoiceFilter(
  1815. choices=LinkStatusChoices
  1816. )
  1817. color = django_filters.MultipleChoiceFilter(
  1818. choices=ColorChoices
  1819. )
  1820. device_id = MultiValueNumberFilter(
  1821. method='filter_by_termination'
  1822. )
  1823. device = MultiValueCharFilter(
  1824. method='filter_by_termination',
  1825. field_name='device__name'
  1826. )
  1827. rack_id = MultiValueNumberFilter(
  1828. method='filter_by_termination',
  1829. field_name='rack_id'
  1830. )
  1831. rack = MultiValueCharFilter(
  1832. method='filter_by_termination',
  1833. field_name='rack__name'
  1834. )
  1835. location_id = MultiValueNumberFilter(
  1836. method='filter_by_termination',
  1837. field_name='location_id'
  1838. )
  1839. location = MultiValueCharFilter(
  1840. method='filter_by_termination',
  1841. field_name='location__name'
  1842. )
  1843. site_id = MultiValueNumberFilter(
  1844. method='filter_by_termination',
  1845. field_name='site_id'
  1846. )
  1847. site = MultiValueCharFilter(
  1848. method='filter_by_termination',
  1849. field_name='site__slug'
  1850. )
  1851. # Termination object filters
  1852. consoleport_id = MultiValueNumberFilter(
  1853. method='filter_by_consoleport'
  1854. )
  1855. consoleserverport_id = MultiValueNumberFilter(
  1856. method='filter_by_consoleserverport'
  1857. )
  1858. powerport_id = MultiValueNumberFilter(
  1859. method='filter_by_powerport'
  1860. )
  1861. poweroutlet_id = MultiValueNumberFilter(
  1862. method='filter_by_poweroutlet'
  1863. )
  1864. interface_id = MultiValueNumberFilter(
  1865. method='filter_by_interface'
  1866. )
  1867. frontport_id = MultiValueNumberFilter(
  1868. method='filter_by_frontport'
  1869. )
  1870. rearport_id = MultiValueNumberFilter(
  1871. method='filter_by_rearport'
  1872. )
  1873. powerfeed_id = MultiValueNumberFilter(
  1874. method='filter_by_powerfeed'
  1875. )
  1876. circuittermination_id = MultiValueNumberFilter(
  1877. method='filter_by_circuittermination'
  1878. )
  1879. class Meta:
  1880. model = Cable
  1881. fields = ('id', 'label', 'length', 'length_unit', 'description')
  1882. def search(self, queryset, name, value):
  1883. if not value.strip():
  1884. return queryset
  1885. qs_filter = (
  1886. Q(label__icontains=value) |
  1887. Q(description__icontains=value)
  1888. )
  1889. return queryset.filter(qs_filter)
  1890. def filter_by_termination(self, queryset, name, value):
  1891. # Filter by a related object cached on CableTermination. Note the underscore preceding the field name.
  1892. # Supported objects: device, rack, location, site
  1893. return queryset.filter(**{f'terminations___{name}__in': value}).distinct()
  1894. def filter_by_cable_end(self, queryset, name, value, side):
  1895. # Filter by termination id and cable_end type
  1896. return queryset.filter(**{f'{name}__in': value, 'terminations__cable_end': side}).distinct()
  1897. def filter_by_cable_end_a(self, queryset, name, value):
  1898. # Filter by termination id and cable_end type
  1899. return self.filter_by_cable_end(queryset, name, value, CableEndChoices.SIDE_A)
  1900. def filter_by_cable_end_b(self, queryset, name, value):
  1901. # Filter by termination id and cable_end type
  1902. return self.filter_by_cable_end(queryset, name, value, CableEndChoices.SIDE_B)
  1903. def _unterminated(self, queryset, name, value):
  1904. if value:
  1905. terminated_ids = (
  1906. queryset.filter(terminations__cable_end=CableEndChoices.SIDE_A)
  1907. .filter(terminations__cable_end=CableEndChoices.SIDE_B)
  1908. .values("id")
  1909. )
  1910. return queryset.exclude(id__in=terminated_ids)
  1911. else:
  1912. return queryset.filter(terminations__cable_end=CableEndChoices.SIDE_A).filter(
  1913. terminations__cable_end=CableEndChoices.SIDE_B
  1914. )
  1915. def filter_by_termination_object(self, queryset, model, value):
  1916. # Filter by specific termination object(s)
  1917. content_type = ContentType.objects.get_for_model(model)
  1918. cable_ids = CableTermination.objects.filter(
  1919. termination_type=content_type,
  1920. termination_id__in=value
  1921. ).values_list('cable', flat=True)
  1922. return queryset.filter(pk__in=cable_ids)
  1923. def filter_by_consoleport(self, queryset, name, value):
  1924. return self.filter_by_termination_object(queryset, ConsolePort, value)
  1925. def filter_by_consoleserverport(self, queryset, name, value):
  1926. return self.filter_by_termination_object(queryset, ConsoleServerPort, value)
  1927. def filter_by_powerport(self, queryset, name, value):
  1928. return self.filter_by_termination_object(queryset, PowerPort, value)
  1929. def filter_by_poweroutlet(self, queryset, name, value):
  1930. return self.filter_by_termination_object(queryset, PowerOutlet, value)
  1931. def filter_by_interface(self, queryset, name, value):
  1932. return self.filter_by_termination_object(queryset, Interface, value)
  1933. def filter_by_frontport(self, queryset, name, value):
  1934. return self.filter_by_termination_object(queryset, FrontPort, value)
  1935. def filter_by_rearport(self, queryset, name, value):
  1936. return self.filter_by_termination_object(queryset, RearPort, value)
  1937. def filter_by_powerfeed(self, queryset, name, value):
  1938. return self.filter_by_termination_object(queryset, PowerFeed, value)
  1939. def filter_by_circuittermination(self, queryset, name, value):
  1940. return self.filter_by_termination_object(queryset, CircuitTermination, value)
  1941. class CableTerminationFilterSet(ChangeLoggedModelFilterSet):
  1942. termination_type = ContentTypeFilter()
  1943. class Meta:
  1944. model = CableTermination
  1945. fields = ('id', 'cable', 'cable_end', 'termination_type', 'termination_id')
  1946. class PowerPanelFilterSet(NetBoxModelFilterSet, ContactModelFilterSet):
  1947. region_id = TreeNodeMultipleChoiceFilter(
  1948. queryset=Region.objects.all(),
  1949. field_name='site__region',
  1950. lookup_expr='in',
  1951. label=_('Region (ID)'),
  1952. )
  1953. region = TreeNodeMultipleChoiceFilter(
  1954. queryset=Region.objects.all(),
  1955. field_name='site__region',
  1956. lookup_expr='in',
  1957. to_field_name='slug',
  1958. label=_('Region (slug)'),
  1959. )
  1960. site_group_id = TreeNodeMultipleChoiceFilter(
  1961. queryset=SiteGroup.objects.all(),
  1962. field_name='site__group',
  1963. lookup_expr='in',
  1964. label=_('Site group (ID)'),
  1965. )
  1966. site_group = TreeNodeMultipleChoiceFilter(
  1967. queryset=SiteGroup.objects.all(),
  1968. field_name='site__group',
  1969. lookup_expr='in',
  1970. to_field_name='slug',
  1971. label=_('Site group (slug)'),
  1972. )
  1973. site_id = django_filters.ModelMultipleChoiceFilter(
  1974. queryset=Site.objects.all(),
  1975. label=_('Site (ID)'),
  1976. )
  1977. site = django_filters.ModelMultipleChoiceFilter(
  1978. field_name='site__slug',
  1979. queryset=Site.objects.all(),
  1980. to_field_name='slug',
  1981. label=_('Site name (slug)'),
  1982. )
  1983. location_id = TreeNodeMultipleChoiceFilter(
  1984. queryset=Location.objects.all(),
  1985. field_name='location',
  1986. lookup_expr='in',
  1987. label=_('Location (ID)'),
  1988. )
  1989. class Meta:
  1990. model = PowerPanel
  1991. fields = ('id', 'name', 'description')
  1992. def search(self, queryset, name, value):
  1993. if not value.strip():
  1994. return queryset
  1995. qs_filter = (
  1996. Q(name__icontains=value) |
  1997. Q(description__icontains=value)
  1998. )
  1999. return queryset.filter(qs_filter)
  2000. class PowerFeedFilterSet(NetBoxModelFilterSet, CabledObjectFilterSet, PathEndpointFilterSet, TenancyFilterSet):
  2001. region_id = TreeNodeMultipleChoiceFilter(
  2002. queryset=Region.objects.all(),
  2003. field_name='power_panel__site__region',
  2004. lookup_expr='in',
  2005. label=_('Region (ID)'),
  2006. )
  2007. region = TreeNodeMultipleChoiceFilter(
  2008. queryset=Region.objects.all(),
  2009. field_name='power_panel__site__region',
  2010. lookup_expr='in',
  2011. to_field_name='slug',
  2012. label=_('Region (slug)'),
  2013. )
  2014. site_group_id = TreeNodeMultipleChoiceFilter(
  2015. queryset=SiteGroup.objects.all(),
  2016. field_name='power_panel__site__group',
  2017. lookup_expr='in',
  2018. label=_('Site group (ID)'),
  2019. )
  2020. site_group = TreeNodeMultipleChoiceFilter(
  2021. queryset=SiteGroup.objects.all(),
  2022. field_name='power_panel__site__group',
  2023. lookup_expr='in',
  2024. to_field_name='slug',
  2025. label=_('Site group (slug)'),
  2026. )
  2027. site_id = django_filters.ModelMultipleChoiceFilter(
  2028. field_name='power_panel__site',
  2029. queryset=Site.objects.all(),
  2030. label=_('Site (ID)'),
  2031. )
  2032. site = django_filters.ModelMultipleChoiceFilter(
  2033. field_name='power_panel__site__slug',
  2034. queryset=Site.objects.all(),
  2035. to_field_name='slug',
  2036. label=_('Site name (slug)'),
  2037. )
  2038. power_panel_id = django_filters.ModelMultipleChoiceFilter(
  2039. queryset=PowerPanel.objects.all(),
  2040. label=_('Power panel (ID)'),
  2041. )
  2042. rack_id = django_filters.ModelMultipleChoiceFilter(
  2043. field_name='rack',
  2044. queryset=Rack.objects.all(),
  2045. label=_('Rack (ID)'),
  2046. )
  2047. status = django_filters.MultipleChoiceFilter(
  2048. choices=PowerFeedStatusChoices,
  2049. null_value=None
  2050. )
  2051. class Meta:
  2052. model = PowerFeed
  2053. fields = (
  2054. 'id', 'name', 'status', 'type', 'supply', 'phase', 'voltage', 'amperage', 'max_utilization',
  2055. 'available_power', 'mark_connected', 'cable_end', 'description',
  2056. )
  2057. def search(self, queryset, name, value):
  2058. if not value.strip():
  2059. return queryset
  2060. qs_filter = (
  2061. Q(name__icontains=value) |
  2062. Q(description__icontains=value) |
  2063. Q(power_panel__name__icontains=value) |
  2064. Q(comments__icontains=value)
  2065. )
  2066. return queryset.filter(qs_filter)
  2067. #
  2068. # Connection filter sets
  2069. #
  2070. class ConnectionFilterSet(BaseFilterSet):
  2071. q = django_filters.CharFilter(
  2072. method='search',
  2073. label=_('Search'),
  2074. )
  2075. site_id = MultiValueNumberFilter(
  2076. method='filter_connections',
  2077. field_name='device__site_id'
  2078. )
  2079. site = MultiValueCharFilter(
  2080. method='filter_connections',
  2081. field_name='device__site__slug'
  2082. )
  2083. device_id = MultiValueNumberFilter(
  2084. method='filter_connections',
  2085. field_name='device_id'
  2086. )
  2087. device = MultiValueCharFilter(
  2088. method='filter_connections',
  2089. field_name='device__name'
  2090. )
  2091. def filter_connections(self, queryset, name, value):
  2092. if not value:
  2093. return queryset
  2094. return queryset.filter(**{f'{name}__in': value})
  2095. def search(self, queryset, name, value):
  2096. if not value.strip():
  2097. return queryset
  2098. qs_filter = (
  2099. Q(device__name__icontains=value) |
  2100. Q(cable__label__icontains=value)
  2101. )
  2102. return queryset.filter(qs_filter)
  2103. class ConsoleConnectionFilterSet(ConnectionFilterSet):
  2104. class Meta:
  2105. model = ConsolePort
  2106. fields = ('name',)
  2107. class PowerConnectionFilterSet(ConnectionFilterSet):
  2108. class Meta:
  2109. model = PowerPort
  2110. fields = ('name',)
  2111. class InterfaceConnectionFilterSet(ConnectionFilterSet):
  2112. class Meta:
  2113. model = Interface
  2114. fields = tuple()