filtersets.py 85 KB

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