filtersets.py 112 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494
  1. import django_filters
  2. import netaddr
  3. from django.contrib.contenttypes.models import ContentType
  4. from django.db.models import Func, IntegerField, Q
  5. from django.utils.translation import gettext as _
  6. from drf_spectacular.types import OpenApiTypes
  7. from drf_spectacular.utils import extend_schema_field
  8. from netaddr.core import AddrFormatError
  9. from circuits.models import CircuitTermination, VirtualCircuit, VirtualCircuitTermination
  10. from extras.filtersets import LocalConfigContextFilterSet
  11. from extras.models import ConfigTemplate
  12. from ipam.filtersets import PrimaryIPFilterSet
  13. from ipam.models import ASN, VRF, IPAddress, VLANTranslationPolicy
  14. from netbox.choices import ColorChoices, DiameterUnitChoices, FlowRateUnitChoices
  15. from netbox.filtersets import (
  16. AttributeFiltersMixin,
  17. BaseFilterSet,
  18. ChangeLoggedModelFilterSet,
  19. NestedGroupModelFilterSet,
  20. NetBoxModelFilterSet,
  21. OrganizationalModelFilterSet,
  22. PrimaryModelFilterSet,
  23. )
  24. from tenancy.filtersets import ContactModelFilterSet, TenancyFilterSet
  25. from tenancy.models import *
  26. from users.filterset_mixins import OwnerFilterMixin
  27. from users.models import User
  28. from utilities.filters import (
  29. MultiValueBigNumberFilter,
  30. MultiValueCharFilter,
  31. MultiValueContentTypeFilter,
  32. MultiValueMACAddressFilter,
  33. MultiValueNumberFilter,
  34. MultiValueWWNFilter,
  35. NumericArrayFilter,
  36. TreeNodeMultipleChoiceFilter,
  37. )
  38. from utilities.filtersets import register_filterset
  39. from virtualization.models import Cluster, ClusterGroup, VirtualMachine, VMInterface
  40. from vpn.models import L2VPN
  41. from wireless.choices import WirelessChannelChoices, WirelessRoleChoices
  42. from wireless.models import WirelessLAN, WirelessLink
  43. from .choices import *
  44. from .constants import *
  45. from .models import *
  46. __all__ = (
  47. 'CableBundleFilterSet',
  48. 'CableFilterSet',
  49. 'CableTerminationFilterSet',
  50. 'CabledObjectFilterSet',
  51. 'CommonInterfaceFilterSet',
  52. 'ConsoleConnectionFilterSet',
  53. 'ConsolePortFilterSet',
  54. 'ConsolePortTemplateFilterSet',
  55. 'ConsoleServerPortFilterSet',
  56. 'ConsoleServerPortTemplateFilterSet',
  57. 'CoolingFeedFilterSet',
  58. 'CoolingIntakeFilterSet',
  59. 'CoolingIntakeTemplateFilterSet',
  60. 'CoolingOutflowFilterSet',
  61. 'CoolingOutflowTemplateFilterSet',
  62. 'CoolingSourceFilterSet',
  63. 'DeviceBayFilterSet',
  64. 'DeviceBayTemplateFilterSet',
  65. 'DeviceFilterSet',
  66. 'DeviceRoleFilterSet',
  67. 'DeviceTypeFilterSet',
  68. 'FrontPortFilterSet',
  69. 'FrontPortTemplateFilterSet',
  70. 'InterfaceConnectionFilterSet',
  71. 'InterfaceFilterSet',
  72. 'InterfaceTemplateFilterSet',
  73. 'InventoryItemFilterSet',
  74. 'InventoryItemRoleFilterSet',
  75. 'InventoryItemTemplateFilterSet',
  76. 'LocationFilterSet',
  77. 'MACAddressFilterSet',
  78. 'ManufacturerFilterSet',
  79. 'ModuleBayFilterSet',
  80. 'ModuleBayTemplateFilterSet',
  81. 'ModuleBayTypeFilterSet',
  82. 'ModuleFilterSet',
  83. 'ModuleTypeFilterSet',
  84. 'ModuleTypeProfileFilterSet',
  85. 'PathEndpointFilterSet',
  86. 'PlatformFilterSet',
  87. 'PowerConnectionFilterSet',
  88. 'PowerFeedFilterSet',
  89. 'PowerOutletFilterSet',
  90. 'PowerOutletTemplateFilterSet',
  91. 'PowerPanelFilterSet',
  92. 'PowerPortFilterSet',
  93. 'PowerPortTemplateFilterSet',
  94. 'RackFilterSet',
  95. 'RackGroupFilterSet',
  96. 'RackReservationFilterSet',
  97. 'RackRoleFilterSet',
  98. 'RackTypeFilterSet',
  99. 'RearPortFilterSet',
  100. 'RearPortTemplateFilterSet',
  101. 'RegionFilterSet',
  102. 'SiteFilterSet',
  103. 'SiteGroupFilterSet',
  104. 'VirtualChassisFilterSet',
  105. 'VirtualDeviceContextFilterSet',
  106. )
  107. @register_filterset
  108. class RegionFilterSet(NestedGroupModelFilterSet, ContactModelFilterSet):
  109. parent_id = django_filters.ModelMultipleChoiceFilter(
  110. queryset=Region.objects.all(),
  111. distinct=False,
  112. label=_('Parent region (ID)'),
  113. )
  114. parent = django_filters.ModelMultipleChoiceFilter(
  115. field_name='parent__slug',
  116. queryset=Region.objects.all(),
  117. distinct=False,
  118. to_field_name='slug',
  119. label=_('Parent region (slug)'),
  120. )
  121. ancestor_id = TreeNodeMultipleChoiceFilter(
  122. queryset=Region.objects.all(),
  123. field_name='parent',
  124. lookup_expr='in',
  125. label=_('Region (ID)'),
  126. )
  127. ancestor = TreeNodeMultipleChoiceFilter(
  128. queryset=Region.objects.all(),
  129. field_name='parent',
  130. lookup_expr='in',
  131. to_field_name='slug',
  132. label=_('Region (slug)'),
  133. )
  134. class Meta:
  135. model = Region
  136. fields = ('id', 'name', 'slug', 'description')
  137. @register_filterset
  138. class SiteGroupFilterSet(NestedGroupModelFilterSet, ContactModelFilterSet):
  139. parent_id = django_filters.ModelMultipleChoiceFilter(
  140. queryset=SiteGroup.objects.all(),
  141. distinct=False,
  142. label=_('Parent site group (ID)'),
  143. )
  144. parent = django_filters.ModelMultipleChoiceFilter(
  145. field_name='parent__slug',
  146. queryset=SiteGroup.objects.all(),
  147. distinct=False,
  148. to_field_name='slug',
  149. label=_('Parent site group (slug)'),
  150. )
  151. ancestor_id = TreeNodeMultipleChoiceFilter(
  152. queryset=SiteGroup.objects.all(),
  153. field_name='parent',
  154. lookup_expr='in',
  155. label=_('Site group (ID)'),
  156. )
  157. ancestor = TreeNodeMultipleChoiceFilter(
  158. queryset=SiteGroup.objects.all(),
  159. field_name='parent',
  160. lookup_expr='in',
  161. to_field_name='slug',
  162. label=_('Site group (slug)'),
  163. )
  164. class Meta:
  165. model = SiteGroup
  166. fields = ('id', 'name', 'slug', 'description')
  167. @register_filterset
  168. class SiteFilterSet(PrimaryModelFilterSet, TenancyFilterSet, ContactModelFilterSet):
  169. status = django_filters.MultipleChoiceFilter(
  170. choices=SiteStatusChoices,
  171. distinct=False,
  172. null_value=None
  173. )
  174. region_id = TreeNodeMultipleChoiceFilter(
  175. queryset=Region.objects.all(),
  176. field_name='region',
  177. lookup_expr='in',
  178. label=_('Region (ID)'),
  179. )
  180. region = TreeNodeMultipleChoiceFilter(
  181. queryset=Region.objects.all(),
  182. lookup_expr='in',
  183. to_field_name='slug',
  184. label=_('Region (slug)'),
  185. )
  186. group_id = TreeNodeMultipleChoiceFilter(
  187. queryset=SiteGroup.objects.all(),
  188. field_name='group',
  189. lookup_expr='in',
  190. label=_('Group (ID)'),
  191. )
  192. group = TreeNodeMultipleChoiceFilter(
  193. queryset=SiteGroup.objects.all(),
  194. lookup_expr='in',
  195. to_field_name='slug',
  196. label=_('Group (slug)'),
  197. )
  198. asn = django_filters.ModelMultipleChoiceFilter(
  199. field_name='asns__asn',
  200. queryset=ASN.objects.all(),
  201. to_field_name='asn',
  202. label=_('AS (ID)'),
  203. )
  204. asn_id = django_filters.ModelMultipleChoiceFilter(
  205. field_name='asns',
  206. queryset=ASN.objects.all(),
  207. label=_('AS (ID)'),
  208. )
  209. time_zone = MultiValueCharFilter()
  210. class Meta:
  211. model = Site
  212. fields = ('id', 'name', 'slug', 'facility', 'latitude', 'longitude', 'description')
  213. def search(self, queryset, name, value):
  214. if not value.strip():
  215. return queryset
  216. qs_filter = (
  217. Q(name__icontains=value) |
  218. Q(facility__icontains=value) |
  219. Q(description__icontains=value) |
  220. Q(physical_address__icontains=value) |
  221. Q(shipping_address__icontains=value) |
  222. Q(comments__icontains=value)
  223. )
  224. try:
  225. qs_filter |= Q(asns__asn=int(value.strip()))
  226. except ValueError:
  227. pass
  228. return queryset.filter(qs_filter).distinct()
  229. @register_filterset
  230. class LocationFilterSet(TenancyFilterSet, ContactModelFilterSet, NestedGroupModelFilterSet):
  231. region_id = TreeNodeMultipleChoiceFilter(
  232. queryset=Region.objects.all(),
  233. field_name='site__region',
  234. lookup_expr='in',
  235. label=_('Region (ID)'),
  236. )
  237. region = TreeNodeMultipleChoiceFilter(
  238. queryset=Region.objects.all(),
  239. field_name='site__region',
  240. lookup_expr='in',
  241. to_field_name='slug',
  242. label=_('Region (slug)'),
  243. )
  244. site_group_id = TreeNodeMultipleChoiceFilter(
  245. queryset=SiteGroup.objects.all(),
  246. field_name='site__group',
  247. lookup_expr='in',
  248. label=_('Site group (ID)'),
  249. )
  250. site_group = TreeNodeMultipleChoiceFilter(
  251. queryset=SiteGroup.objects.all(),
  252. field_name='site__group',
  253. lookup_expr='in',
  254. to_field_name='slug',
  255. label=_('Site group (slug)'),
  256. )
  257. site_id = django_filters.ModelMultipleChoiceFilter(
  258. queryset=Site.objects.all(),
  259. distinct=False,
  260. label=_('Site (ID)'),
  261. )
  262. site = django_filters.ModelMultipleChoiceFilter(
  263. field_name='site__slug',
  264. queryset=Site.objects.all(),
  265. distinct=False,
  266. to_field_name='slug',
  267. label=_('Site (slug)'),
  268. )
  269. parent_id = django_filters.ModelMultipleChoiceFilter(
  270. queryset=Location.objects.all(),
  271. distinct=False,
  272. label=_('Parent location (ID)'),
  273. )
  274. parent = django_filters.ModelMultipleChoiceFilter(
  275. field_name='parent__slug',
  276. queryset=Location.objects.all(),
  277. distinct=False,
  278. to_field_name='slug',
  279. label=_('Parent location (slug)'),
  280. )
  281. ancestor_id = TreeNodeMultipleChoiceFilter(
  282. queryset=Location.objects.all(),
  283. field_name='parent',
  284. lookup_expr='in',
  285. label=_('Location (ID)'),
  286. )
  287. ancestor = TreeNodeMultipleChoiceFilter(
  288. queryset=Location.objects.all(),
  289. field_name='parent',
  290. lookup_expr='in',
  291. to_field_name='slug',
  292. label=_('Location (slug)'),
  293. )
  294. status = django_filters.MultipleChoiceFilter(
  295. choices=LocationStatusChoices,
  296. distinct=False,
  297. null_value=None
  298. )
  299. class Meta:
  300. model = Location
  301. fields = ('id', 'name', 'slug', 'facility', 'description')
  302. def search(self, queryset, name, value):
  303. # Extend `search()` to include querying on Location.facility
  304. if value.strip():
  305. return super().search(queryset, name, value) | queryset.filter(facility__icontains=value)
  306. return queryset
  307. @register_filterset
  308. class RackGroupFilterSet(OrganizationalModelFilterSet):
  309. class Meta:
  310. model = RackGroup
  311. fields = ('id', 'name', 'slug', 'description')
  312. @register_filterset
  313. class RackRoleFilterSet(OrganizationalModelFilterSet):
  314. class Meta:
  315. model = RackRole
  316. fields = ('id', 'name', 'slug', 'color', 'description')
  317. @register_filterset
  318. class RackTypeFilterSet(PrimaryModelFilterSet):
  319. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  320. queryset=Manufacturer.objects.all(),
  321. distinct=False,
  322. label=_('Manufacturer (ID)'),
  323. )
  324. manufacturer = django_filters.ModelMultipleChoiceFilter(
  325. field_name='manufacturer__slug',
  326. queryset=Manufacturer.objects.all(),
  327. distinct=False,
  328. to_field_name='slug',
  329. label=_('Manufacturer (slug)'),
  330. )
  331. form_factor = django_filters.MultipleChoiceFilter(
  332. choices=RackFormFactorChoices,
  333. distinct=False,
  334. )
  335. width = django_filters.MultipleChoiceFilter(
  336. choices=RackWidthChoices,
  337. distinct=False,
  338. )
  339. cooling_capability = django_filters.MultipleChoiceFilter(
  340. choices=RackCoolingCapabilityChoices,
  341. distinct=False,
  342. )
  343. class Meta:
  344. model = RackType
  345. fields = (
  346. 'id', 'model', 'slug', 'u_height', 'starting_unit', 'desc_units', 'outer_width', 'outer_height',
  347. 'outer_depth', 'outer_unit', 'mounting_depth', 'weight', 'max_weight', 'weight_unit', 'cooling_capacity',
  348. 'description',
  349. # Counters
  350. 'rack_count',
  351. )
  352. def search(self, queryset, name, value):
  353. if not value.strip():
  354. return queryset
  355. return queryset.filter(
  356. Q(model__icontains=value) |
  357. Q(description__icontains=value) |
  358. Q(comments__icontains=value)
  359. )
  360. @register_filterset
  361. class RackFilterSet(PrimaryModelFilterSet, TenancyFilterSet, ContactModelFilterSet):
  362. region_id = TreeNodeMultipleChoiceFilter(
  363. queryset=Region.objects.all(),
  364. field_name='site__region',
  365. lookup_expr='in',
  366. label=_('Region (ID)'),
  367. )
  368. region = TreeNodeMultipleChoiceFilter(
  369. queryset=Region.objects.all(),
  370. field_name='site__region',
  371. lookup_expr='in',
  372. to_field_name='slug',
  373. label=_('Region (slug)'),
  374. )
  375. site_group_id = TreeNodeMultipleChoiceFilter(
  376. queryset=SiteGroup.objects.all(),
  377. field_name='site__group',
  378. lookup_expr='in',
  379. label=_('Site group (ID)'),
  380. )
  381. site_group = TreeNodeMultipleChoiceFilter(
  382. queryset=SiteGroup.objects.all(),
  383. field_name='site__group',
  384. lookup_expr='in',
  385. to_field_name='slug',
  386. label=_('Site group (slug)'),
  387. )
  388. site_id = django_filters.ModelMultipleChoiceFilter(
  389. queryset=Site.objects.all(),
  390. distinct=False,
  391. label=_('Site (ID)'),
  392. )
  393. site = django_filters.ModelMultipleChoiceFilter(
  394. field_name='site__slug',
  395. queryset=Site.objects.all(),
  396. distinct=False,
  397. to_field_name='slug',
  398. label=_('Site (slug)'),
  399. )
  400. location_id = TreeNodeMultipleChoiceFilter(
  401. queryset=Location.objects.all(),
  402. field_name='location',
  403. lookup_expr='in',
  404. label=_('Location (ID)'),
  405. )
  406. location = TreeNodeMultipleChoiceFilter(
  407. queryset=Location.objects.all(),
  408. field_name='location',
  409. lookup_expr='in',
  410. to_field_name='slug',
  411. label=_('Location (slug)'),
  412. )
  413. group_id = django_filters.ModelMultipleChoiceFilter(
  414. queryset=RackGroup.objects.all(),
  415. distinct=False,
  416. label=_('Group (ID)'),
  417. )
  418. group = django_filters.ModelMultipleChoiceFilter(
  419. field_name='group__slug',
  420. queryset=RackGroup.objects.all(),
  421. distinct=False,
  422. to_field_name='slug',
  423. label=_('Group (slug)'),
  424. )
  425. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  426. field_name='rack_type__manufacturer',
  427. queryset=Manufacturer.objects.all(),
  428. distinct=False,
  429. label=_('Manufacturer (ID)'),
  430. )
  431. manufacturer = django_filters.ModelMultipleChoiceFilter(
  432. field_name='rack_type__manufacturer__slug',
  433. queryset=Manufacturer.objects.all(),
  434. distinct=False,
  435. to_field_name='slug',
  436. label=_('Manufacturer (slug)'),
  437. )
  438. rack_type = django_filters.ModelMultipleChoiceFilter(
  439. field_name='rack_type__slug',
  440. queryset=RackType.objects.all(),
  441. distinct=False,
  442. to_field_name='slug',
  443. label=_('Rack type (slug)'),
  444. )
  445. rack_type_id = django_filters.ModelMultipleChoiceFilter(
  446. queryset=RackType.objects.all(),
  447. distinct=False,
  448. label=_('Rack type (ID)'),
  449. )
  450. status = django_filters.MultipleChoiceFilter(
  451. choices=RackStatusChoices,
  452. distinct=False,
  453. null_value=None
  454. )
  455. form_factor = django_filters.MultipleChoiceFilter(
  456. choices=RackFormFactorChoices,
  457. distinct=False,
  458. )
  459. width = django_filters.MultipleChoiceFilter(
  460. choices=RackWidthChoices,
  461. distinct=False,
  462. )
  463. role_id = django_filters.ModelMultipleChoiceFilter(
  464. queryset=RackRole.objects.all(),
  465. distinct=False,
  466. label=_('Role (ID)'),
  467. )
  468. role = django_filters.ModelMultipleChoiceFilter(
  469. field_name='role__slug',
  470. queryset=RackRole.objects.all(),
  471. distinct=False,
  472. to_field_name='slug',
  473. label=_('Role (slug)'),
  474. )
  475. serial = MultiValueCharFilter(
  476. lookup_expr='iexact'
  477. )
  478. cooling_capability = django_filters.MultipleChoiceFilter(
  479. choices=RackCoolingCapabilityChoices,
  480. distinct=False,
  481. )
  482. class Meta:
  483. model = Rack
  484. fields = (
  485. 'id', 'name', 'facility_id', 'asset_tag', 'u_height', 'starting_unit', 'desc_units', 'outer_width',
  486. 'outer_height', 'outer_depth', 'outer_unit', 'mounting_depth', 'airflow', 'cooling_capacity',
  487. 'weight', 'max_weight', 'weight_unit', 'description',
  488. )
  489. def search(self, queryset, name, value):
  490. if not value.strip():
  491. return queryset
  492. return queryset.filter(
  493. Q(name__icontains=value) |
  494. Q(facility_id__icontains=value) |
  495. Q(serial__icontains=value.strip()) |
  496. Q(asset_tag__icontains=value.strip()) |
  497. Q(description__icontains=value) |
  498. Q(comments__icontains=value)
  499. )
  500. @register_filterset
  501. class RackReservationFilterSet(PrimaryModelFilterSet, TenancyFilterSet):
  502. rack_id = django_filters.ModelMultipleChoiceFilter(
  503. queryset=Rack.objects.all(),
  504. distinct=False,
  505. label=_('Rack (ID)'),
  506. )
  507. site_id = django_filters.ModelMultipleChoiceFilter(
  508. field_name='rack__site',
  509. queryset=Site.objects.all(),
  510. distinct=False,
  511. label=_('Site (ID)'),
  512. )
  513. site = django_filters.ModelMultipleChoiceFilter(
  514. field_name='rack__site__slug',
  515. queryset=Site.objects.all(),
  516. distinct=False,
  517. to_field_name='slug',
  518. label=_('Site (slug)'),
  519. )
  520. region_id = TreeNodeMultipleChoiceFilter(
  521. queryset=Region.objects.all(),
  522. field_name='rack__site__region',
  523. lookup_expr='in',
  524. label=_('Region (ID)'),
  525. )
  526. region = TreeNodeMultipleChoiceFilter(
  527. queryset=Region.objects.all(),
  528. field_name='rack__site__region',
  529. lookup_expr='in',
  530. to_field_name='slug',
  531. label=_('Region (slug)'),
  532. )
  533. site_group_id = TreeNodeMultipleChoiceFilter(
  534. queryset=SiteGroup.objects.all(),
  535. field_name='rack__site__group',
  536. lookup_expr='in',
  537. label=_('Site group (ID)'),
  538. )
  539. site_group = TreeNodeMultipleChoiceFilter(
  540. queryset=SiteGroup.objects.all(),
  541. field_name='rack__site__group',
  542. lookup_expr='in',
  543. to_field_name='slug',
  544. label=_('Site group (slug)'),
  545. )
  546. location_id = TreeNodeMultipleChoiceFilter(
  547. queryset=Location.objects.all(),
  548. field_name='rack__location',
  549. lookup_expr='in',
  550. label=_('Location (ID)'),
  551. )
  552. location = TreeNodeMultipleChoiceFilter(
  553. queryset=Location.objects.all(),
  554. field_name='rack__location',
  555. lookup_expr='in',
  556. to_field_name='slug',
  557. label=_('Location (slug)'),
  558. )
  559. group_id = django_filters.ModelMultipleChoiceFilter(
  560. queryset=RackGroup.objects.all(),
  561. field_name='rack__group',
  562. distinct=False,
  563. label=_('Group (ID)'),
  564. )
  565. group = django_filters.ModelMultipleChoiceFilter(
  566. field_name='rack__group__slug',
  567. queryset=RackGroup.objects.all(),
  568. distinct=False,
  569. to_field_name='slug',
  570. label=_('Group (slug)'),
  571. )
  572. status = django_filters.MultipleChoiceFilter(
  573. choices=RackReservationStatusChoices,
  574. distinct=False,
  575. null_value=None
  576. )
  577. user_id = django_filters.ModelMultipleChoiceFilter(
  578. queryset=User.objects.all(),
  579. distinct=False,
  580. label=_('User (ID)'),
  581. )
  582. user = django_filters.ModelMultipleChoiceFilter(
  583. field_name='user__username',
  584. queryset=User.objects.all(),
  585. distinct=False,
  586. to_field_name='username',
  587. label=_('User (name)'),
  588. )
  589. unit = NumericArrayFilter(
  590. field_name='units',
  591. lookup_expr='contains'
  592. )
  593. unit_count_min = django_filters.NumberFilter(
  594. field_name='unit_count',
  595. lookup_expr='gte',
  596. label=_('Minimum unit count'),
  597. )
  598. unit_count_max = django_filters.NumberFilter(
  599. field_name='unit_count',
  600. lookup_expr='lte',
  601. label=_('Maximum unit count'),
  602. )
  603. class Meta:
  604. model = RackReservation
  605. fields = ('id', 'created', 'description')
  606. def filter_queryset(self, queryset):
  607. # Annotate unit_count here so unit_count_min/unit_count_max filters can reference it.
  608. # When called from the list view the queryset is already annotated; Django silently
  609. # overwrites a duplicate annotation with the same expression, so this is safe.
  610. queryset = queryset.annotate(
  611. unit_count=Func('units', function='CARDINALITY', output_field=IntegerField())
  612. )
  613. return super().filter_queryset(queryset)
  614. def search(self, queryset, name, value):
  615. if not value.strip():
  616. return queryset
  617. return queryset.filter(
  618. Q(rack__name__icontains=value) |
  619. Q(rack__facility_id__icontains=value) |
  620. Q(user__username__icontains=value) |
  621. Q(description__icontains=value)
  622. )
  623. @register_filterset
  624. class ManufacturerFilterSet(OrganizationalModelFilterSet, ContactModelFilterSet):
  625. class Meta:
  626. model = Manufacturer
  627. fields = ('id', 'name', 'slug', 'description')
  628. @register_filterset
  629. class DeviceTypeFilterSet(PrimaryModelFilterSet):
  630. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  631. queryset=Manufacturer.objects.all(),
  632. distinct=False,
  633. label=_('Manufacturer (ID)'),
  634. )
  635. manufacturer = django_filters.ModelMultipleChoiceFilter(
  636. field_name='manufacturer__slug',
  637. queryset=Manufacturer.objects.all(),
  638. distinct=False,
  639. to_field_name='slug',
  640. label=_('Manufacturer (slug)'),
  641. )
  642. default_platform_id = TreeNodeMultipleChoiceFilter(
  643. queryset=Platform.objects.all(),
  644. field_name='default_platform',
  645. lookup_expr='in',
  646. label=_('Default platform (ID)'),
  647. )
  648. default_platform = TreeNodeMultipleChoiceFilter(
  649. queryset=Platform.objects.all(),
  650. field_name='default_platform',
  651. to_field_name='slug',
  652. lookup_expr='in',
  653. label=_('Default platform (slug)'),
  654. )
  655. has_front_image = django_filters.BooleanFilter(
  656. label=_('Has a front image'),
  657. method='_has_front_image'
  658. )
  659. has_rear_image = django_filters.BooleanFilter(
  660. label=_('Has a rear image'),
  661. method='_has_rear_image'
  662. )
  663. console_ports = django_filters.BooleanFilter(
  664. method='_console_ports',
  665. label=_('Has console ports'),
  666. )
  667. console_server_ports = django_filters.BooleanFilter(
  668. method='_console_server_ports',
  669. label=_('Has console server ports'),
  670. )
  671. power_ports = django_filters.BooleanFilter(
  672. method='_power_ports',
  673. label=_('Has power ports'),
  674. )
  675. power_outlets = django_filters.BooleanFilter(
  676. method='_power_outlets',
  677. label=_('Has power outlets'),
  678. )
  679. interfaces = django_filters.BooleanFilter(
  680. method='_interfaces',
  681. label=_('Has interfaces'),
  682. )
  683. pass_through_ports = django_filters.BooleanFilter(
  684. method='_pass_through_ports',
  685. label=_('Has pass-through ports'),
  686. )
  687. module_bays = django_filters.BooleanFilter(
  688. method='_module_bays',
  689. label=_('Has module bays'),
  690. )
  691. device_bays = django_filters.BooleanFilter(
  692. method='_device_bays',
  693. label=_('Has device bays'),
  694. )
  695. inventory_items = django_filters.BooleanFilter(
  696. method='_inventory_items',
  697. label=_('Has inventory items'),
  698. )
  699. class Meta:
  700. model = DeviceType
  701. fields = (
  702. 'id', 'model', 'slug', 'part_number', 'u_height', 'exclude_from_utilization', 'is_full_depth',
  703. 'subdevice_role', 'airflow', 'cooling_method', 'weight', 'weight_unit', 'end_of_life', 'description',
  704. # Counters
  705. 'console_port_template_count',
  706. 'console_server_port_template_count',
  707. 'power_port_template_count',
  708. 'power_outlet_template_count',
  709. 'cooling_intake_template_count',
  710. 'cooling_outflow_template_count',
  711. 'interface_template_count',
  712. 'front_port_template_count',
  713. 'rear_port_template_count',
  714. 'device_bay_template_count',
  715. 'module_bay_template_count',
  716. 'inventory_item_template_count',
  717. 'device_count',
  718. )
  719. def search(self, queryset, name, value):
  720. if not value.strip():
  721. return queryset
  722. return queryset.filter(
  723. Q(manufacturer__name__icontains=value) |
  724. Q(model__icontains=value) |
  725. Q(part_number__icontains=value) |
  726. Q(description__icontains=value) |
  727. Q(comments__icontains=value)
  728. )
  729. def _has_front_image(self, queryset, name, value):
  730. if value:
  731. return queryset.exclude(front_image='')
  732. return queryset.filter(front_image='')
  733. def _has_rear_image(self, queryset, name, value):
  734. if value:
  735. return queryset.exclude(rear_image='')
  736. return queryset.filter(rear_image='')
  737. def _console_ports(self, queryset, name, value):
  738. return queryset.exclude(consoleporttemplates__isnull=value)
  739. def _console_server_ports(self, queryset, name, value):
  740. return queryset.exclude(consoleserverporttemplates__isnull=value)
  741. def _power_ports(self, queryset, name, value):
  742. return queryset.exclude(powerporttemplates__isnull=value)
  743. def _power_outlets(self, queryset, name, value):
  744. return queryset.exclude(poweroutlettemplates__isnull=value)
  745. def _interfaces(self, queryset, name, value):
  746. return queryset.exclude(interfacetemplates__isnull=value)
  747. def _pass_through_ports(self, queryset, name, value):
  748. return queryset.exclude(
  749. frontporttemplates__isnull=value,
  750. rearporttemplates__isnull=value
  751. )
  752. def _module_bays(self, queryset, name, value):
  753. return queryset.exclude(modulebaytemplates__isnull=value)
  754. def _device_bays(self, queryset, name, value):
  755. return queryset.exclude(devicebaytemplates__isnull=value)
  756. def _inventory_items(self, queryset, name, value):
  757. return queryset.exclude(inventoryitemtemplates__isnull=value)
  758. @register_filterset
  759. class ModuleBayTypeFilterSet(PrimaryModelFilterSet):
  760. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  761. queryset=Manufacturer.objects.all(),
  762. distinct=False,
  763. label=_('Manufacturer (ID)'),
  764. )
  765. manufacturer = django_filters.ModelMultipleChoiceFilter(
  766. field_name='manufacturer__slug',
  767. queryset=Manufacturer.objects.all(),
  768. distinct=False,
  769. to_field_name='slug',
  770. label=_('Manufacturer (slug)'),
  771. )
  772. module_type_id = django_filters.ModelMultipleChoiceFilter(
  773. field_name='module_types',
  774. queryset=ModuleType.objects.all(),
  775. label=_('Module type (ID)'),
  776. )
  777. module_bay_template_id = django_filters.ModelMultipleChoiceFilter(
  778. field_name='module_bay_templates',
  779. queryset=ModuleBayTemplate.objects.all(),
  780. label=_('Module bay template (ID)'),
  781. )
  782. module_bay_id = django_filters.ModelMultipleChoiceFilter(
  783. field_name='module_bays',
  784. queryset=ModuleBay.objects.all(),
  785. label=_('Module bay (ID)'),
  786. )
  787. class Meta:
  788. model = ModuleBayType
  789. fields = ('id', 'name', 'slug', 'color', 'description')
  790. def search(self, queryset, name, value):
  791. if not value.strip():
  792. return queryset
  793. return queryset.filter(
  794. Q(name__icontains=value) |
  795. Q(slug__icontains=value) |
  796. Q(description__icontains=value) |
  797. Q(comments__icontains=value)
  798. )
  799. @register_filterset
  800. class ModuleTypeProfileFilterSet(PrimaryModelFilterSet):
  801. class Meta:
  802. model = ModuleTypeProfile
  803. fields = ('id', 'name', 'description')
  804. def search(self, queryset, name, value):
  805. if not value.strip():
  806. return queryset
  807. return queryset.filter(
  808. Q(name__icontains=value) |
  809. Q(description__icontains=value) |
  810. Q(comments__icontains=value)
  811. )
  812. @register_filterset
  813. class ModuleTypeFilterSet(AttributeFiltersMixin, PrimaryModelFilterSet):
  814. profile_id = django_filters.ModelMultipleChoiceFilter(
  815. queryset=ModuleTypeProfile.objects.all(),
  816. distinct=False,
  817. label=_('Profile (ID)'),
  818. )
  819. profile = django_filters.ModelMultipleChoiceFilter(
  820. field_name='profile__name',
  821. queryset=ModuleTypeProfile.objects.all(),
  822. distinct=False,
  823. to_field_name='name',
  824. label=_('Profile (name)'),
  825. )
  826. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  827. queryset=Manufacturer.objects.all(),
  828. distinct=False,
  829. label=_('Manufacturer (ID)'),
  830. )
  831. manufacturer = django_filters.ModelMultipleChoiceFilter(
  832. field_name='manufacturer__slug',
  833. queryset=Manufacturer.objects.all(),
  834. distinct=False,
  835. to_field_name='slug',
  836. label=_('Manufacturer (slug)'),
  837. )
  838. module_bay_type_id = django_filters.ModelMultipleChoiceFilter(
  839. field_name='module_bay_types',
  840. queryset=ModuleBayType.objects.all(),
  841. distinct=False,
  842. label=_('Module bay type (ID)'),
  843. )
  844. module_bay_type = django_filters.ModelMultipleChoiceFilter(
  845. field_name='module_bay_types__slug',
  846. queryset=ModuleBayType.objects.all(),
  847. distinct=False,
  848. to_field_name='slug',
  849. label=_('Module bay type (slug)'),
  850. )
  851. console_ports = django_filters.BooleanFilter(
  852. method='_console_ports',
  853. label=_('Has console ports'),
  854. )
  855. console_server_ports = django_filters.BooleanFilter(
  856. method='_console_server_ports',
  857. label=_('Has console server ports'),
  858. )
  859. power_ports = django_filters.BooleanFilter(
  860. method='_power_ports',
  861. label=_('Has power ports'),
  862. )
  863. power_outlets = django_filters.BooleanFilter(
  864. method='_power_outlets',
  865. label=_('Has power outlets'),
  866. )
  867. interfaces = django_filters.BooleanFilter(
  868. method='_interfaces',
  869. label=_('Has interfaces'),
  870. )
  871. pass_through_ports = django_filters.BooleanFilter(
  872. method='_pass_through_ports',
  873. label=_('Has pass-through ports'),
  874. )
  875. module_bays = django_filters.BooleanFilter(
  876. method='_module_bays',
  877. label=_('Has module bays'),
  878. )
  879. class Meta:
  880. model = ModuleType
  881. fields = (
  882. 'id', 'model', 'part_number', 'airflow', 'cooling_method', 'weight', 'weight_unit', 'end_of_life',
  883. 'description',
  884. # Counters
  885. 'console_port_template_count',
  886. 'console_server_port_template_count',
  887. 'power_port_template_count',
  888. 'power_outlet_template_count',
  889. 'cooling_intake_template_count',
  890. 'cooling_outflow_template_count',
  891. 'interface_template_count',
  892. 'front_port_template_count',
  893. 'rear_port_template_count',
  894. 'module_bay_template_count',
  895. 'module_count',
  896. )
  897. def search(self, queryset, name, value):
  898. if not value.strip():
  899. return queryset
  900. return queryset.filter(
  901. Q(manufacturer__name__icontains=value) |
  902. Q(model__icontains=value) |
  903. Q(part_number__icontains=value) |
  904. Q(description__icontains=value) |
  905. Q(comments__icontains=value)
  906. )
  907. def _console_ports(self, queryset, name, value):
  908. return queryset.exclude(consoleporttemplates__isnull=value)
  909. def _console_server_ports(self, queryset, name, value):
  910. return queryset.exclude(consoleserverporttemplates__isnull=value)
  911. def _power_ports(self, queryset, name, value):
  912. return queryset.exclude(powerporttemplates__isnull=value)
  913. def _power_outlets(self, queryset, name, value):
  914. return queryset.exclude(poweroutlettemplates__isnull=value)
  915. def _interfaces(self, queryset, name, value):
  916. return queryset.exclude(interfacetemplates__isnull=value)
  917. def _pass_through_ports(self, queryset, name, value):
  918. return queryset.exclude(
  919. frontporttemplates__isnull=value,
  920. rearporttemplates__isnull=value
  921. )
  922. def _module_bays(self, queryset, name, value):
  923. return queryset.exclude(modulebaytemplates__isnull=value)
  924. class DeviceTypeComponentFilterSet(django_filters.FilterSet):
  925. q = django_filters.CharFilter(
  926. method='search',
  927. label=_('Search'),
  928. )
  929. device_type_id = django_filters.ModelMultipleChoiceFilter(
  930. queryset=DeviceType.objects.all(),
  931. distinct=False,
  932. field_name='device_type_id',
  933. label=_('Device type (ID)'),
  934. )
  935. def search(self, queryset, name, value):
  936. if not value.strip():
  937. return queryset
  938. return queryset.filter(
  939. Q(name__icontains=value) |
  940. Q(description__icontains=value)
  941. )
  942. class ModularDeviceTypeComponentFilterSet(DeviceTypeComponentFilterSet):
  943. module_type_id = django_filters.ModelMultipleChoiceFilter(
  944. queryset=ModuleType.objects.all(),
  945. distinct=False,
  946. field_name='module_type_id',
  947. label=_('Module type (ID)'),
  948. )
  949. @register_filterset
  950. class ConsolePortTemplateFilterSet(ChangeLoggedModelFilterSet, ModularDeviceTypeComponentFilterSet):
  951. class Meta:
  952. model = ConsolePortTemplate
  953. fields = ('id', 'name', 'label', 'type', 'description')
  954. @register_filterset
  955. class ConsoleServerPortTemplateFilterSet(ChangeLoggedModelFilterSet, ModularDeviceTypeComponentFilterSet):
  956. class Meta:
  957. model = ConsoleServerPortTemplate
  958. fields = ('id', 'name', 'label', 'type', 'description')
  959. @register_filterset
  960. class PowerPortTemplateFilterSet(ChangeLoggedModelFilterSet, ModularDeviceTypeComponentFilterSet):
  961. class Meta:
  962. model = PowerPortTemplate
  963. fields = ('id', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description')
  964. @register_filterset
  965. class PowerOutletTemplateFilterSet(ChangeLoggedModelFilterSet, ModularDeviceTypeComponentFilterSet):
  966. feed_leg = django_filters.MultipleChoiceFilter(
  967. choices=PowerOutletFeedLegChoices,
  968. distinct=False,
  969. null_value=None
  970. )
  971. power_port_id = django_filters.ModelMultipleChoiceFilter(
  972. queryset=PowerPortTemplate.objects.all(),
  973. distinct=False,
  974. label=_('Power port (ID)'),
  975. )
  976. class Meta:
  977. model = PowerOutletTemplate
  978. fields = ('id', 'name', 'label', 'type', 'color', 'feed_leg', 'description')
  979. @register_filterset
  980. class CoolingIntakeTemplateFilterSet(ChangeLoggedModelFilterSet, ModularDeviceTypeComponentFilterSet):
  981. type = django_filters.MultipleChoiceFilter(
  982. choices=CoolingConnectorTypeChoices,
  983. distinct=False,
  984. null_value=None
  985. )
  986. diameter_unit = django_filters.MultipleChoiceFilter(
  987. choices=DiameterUnitChoices,
  988. distinct=False,
  989. null_value=None
  990. )
  991. max_flow_unit = django_filters.MultipleChoiceFilter(
  992. choices=FlowRateUnitChoices,
  993. distinct=False,
  994. null_value=None
  995. )
  996. class Meta:
  997. model = CoolingIntakeTemplate
  998. fields = (
  999. 'id', 'name', 'label', 'diameter', 'max_flow', 'description',
  1000. )
  1001. @register_filterset
  1002. class CoolingOutflowTemplateFilterSet(ChangeLoggedModelFilterSet, ModularDeviceTypeComponentFilterSet):
  1003. type = django_filters.MultipleChoiceFilter(
  1004. choices=CoolingConnectorTypeChoices,
  1005. distinct=False,
  1006. null_value=None
  1007. )
  1008. diameter_unit = django_filters.MultipleChoiceFilter(
  1009. choices=DiameterUnitChoices,
  1010. distinct=False,
  1011. null_value=None
  1012. )
  1013. cooling_intake_id = django_filters.ModelMultipleChoiceFilter(
  1014. field_name='cooling_intake',
  1015. queryset=CoolingIntakeTemplate.objects.all(),
  1016. distinct=False,
  1017. label=_('Cooling intake (ID)'),
  1018. )
  1019. class Meta:
  1020. model = CoolingOutflowTemplate
  1021. fields = ('id', 'name', 'label', 'diameter', 'description')
  1022. @register_filterset
  1023. class InterfaceTemplateFilterSet(ChangeLoggedModelFilterSet, ModularDeviceTypeComponentFilterSet):
  1024. type = django_filters.MultipleChoiceFilter(
  1025. choices=InterfaceTypeChoices,
  1026. distinct=False,
  1027. null_value=None
  1028. )
  1029. parent_id = django_filters.ModelMultipleChoiceFilter(
  1030. field_name='parent',
  1031. queryset=InterfaceTemplate.objects.all(),
  1032. distinct=False,
  1033. )
  1034. bridge_id = django_filters.ModelMultipleChoiceFilter(
  1035. field_name='bridge',
  1036. queryset=InterfaceTemplate.objects.all(),
  1037. distinct=False,
  1038. )
  1039. poe_mode = django_filters.MultipleChoiceFilter(
  1040. choices=InterfacePoEModeChoices,
  1041. distinct=False,
  1042. )
  1043. poe_type = django_filters.MultipleChoiceFilter(
  1044. choices=InterfacePoETypeChoices,
  1045. distinct=False,
  1046. )
  1047. rf_role = django_filters.MultipleChoiceFilter(
  1048. choices=WirelessRoleChoices,
  1049. distinct=False,
  1050. )
  1051. class Meta:
  1052. model = InterfaceTemplate
  1053. fields = ('id', 'name', 'label', 'type', 'channels', 'channel_id', 'enabled', 'mgmt_only', 'description')
  1054. @register_filterset
  1055. class FrontPortTemplateFilterSet(ChangeLoggedModelFilterSet, ModularDeviceTypeComponentFilterSet):
  1056. type = django_filters.MultipleChoiceFilter(
  1057. choices=PortTypeChoices,
  1058. distinct=False,
  1059. null_value=None
  1060. )
  1061. rear_port_id = django_filters.ModelMultipleChoiceFilter(
  1062. field_name='mappings__rear_port',
  1063. queryset=RearPortTemplate.objects.all(),
  1064. to_field_name='rear_port',
  1065. label=_('Rear port (ID)'),
  1066. )
  1067. class Meta:
  1068. model = FrontPortTemplate
  1069. fields = ('id', 'name', 'label', 'type', 'color', 'positions', 'description')
  1070. @register_filterset
  1071. class RearPortTemplateFilterSet(ChangeLoggedModelFilterSet, ModularDeviceTypeComponentFilterSet):
  1072. type = django_filters.MultipleChoiceFilter(
  1073. choices=PortTypeChoices,
  1074. distinct=False,
  1075. null_value=None
  1076. )
  1077. front_port_id = django_filters.ModelMultipleChoiceFilter(
  1078. field_name='mappings__front_port',
  1079. queryset=FrontPort.objects.all(),
  1080. to_field_name='front_port',
  1081. label=_('Front port (ID)'),
  1082. )
  1083. class Meta:
  1084. model = RearPortTemplate
  1085. fields = ('id', 'name', 'label', 'type', 'color', 'positions', 'description')
  1086. @register_filterset
  1087. class ModuleBayTemplateFilterSet(ChangeLoggedModelFilterSet, ModularDeviceTypeComponentFilterSet):
  1088. module_bay_type_id = django_filters.ModelMultipleChoiceFilter(
  1089. field_name='module_bay_types',
  1090. queryset=ModuleBayType.objects.all(),
  1091. distinct=False,
  1092. label=_('Module bay type (ID)'),
  1093. )
  1094. module_bay_type = django_filters.ModelMultipleChoiceFilter(
  1095. field_name='module_bay_types__slug',
  1096. queryset=ModuleBayType.objects.all(),
  1097. distinct=False,
  1098. to_field_name='slug',
  1099. label=_('Module bay type (slug)'),
  1100. )
  1101. class Meta:
  1102. model = ModuleBayTemplate
  1103. fields = ('id', 'name', 'label', 'position', 'enabled', 'description')
  1104. @register_filterset
  1105. class DeviceBayTemplateFilterSet(ChangeLoggedModelFilterSet, DeviceTypeComponentFilterSet):
  1106. class Meta:
  1107. model = DeviceBayTemplate
  1108. fields = ('id', 'name', 'label', 'enabled', 'description')
  1109. @register_filterset
  1110. class InventoryItemTemplateFilterSet(ChangeLoggedModelFilterSet, DeviceTypeComponentFilterSet):
  1111. parent_id = django_filters.ModelMultipleChoiceFilter(
  1112. queryset=InventoryItemTemplate.objects.all(),
  1113. distinct=False,
  1114. label=_('Parent inventory item (ID)'),
  1115. )
  1116. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  1117. queryset=Manufacturer.objects.all(),
  1118. distinct=False,
  1119. label=_('Manufacturer (ID)'),
  1120. )
  1121. manufacturer = django_filters.ModelMultipleChoiceFilter(
  1122. field_name='manufacturer__slug',
  1123. queryset=Manufacturer.objects.all(),
  1124. distinct=False,
  1125. to_field_name='slug',
  1126. label=_('Manufacturer (slug)'),
  1127. )
  1128. role_id = django_filters.ModelMultipleChoiceFilter(
  1129. queryset=InventoryItemRole.objects.all(),
  1130. distinct=False,
  1131. label=_('Role (ID)'),
  1132. )
  1133. role = django_filters.ModelMultipleChoiceFilter(
  1134. field_name='role__slug',
  1135. queryset=InventoryItemRole.objects.all(),
  1136. distinct=False,
  1137. to_field_name='slug',
  1138. label=_('Role (slug)'),
  1139. )
  1140. component_type = MultiValueContentTypeFilter()
  1141. component_id = MultiValueNumberFilter()
  1142. class Meta:
  1143. model = InventoryItemTemplate
  1144. fields = ('id', 'name', 'label', 'part_id', 'description')
  1145. def search(self, queryset, name, value):
  1146. if not value.strip():
  1147. return queryset
  1148. qs_filter = (
  1149. Q(name__icontains=value) |
  1150. Q(part_id__icontains=value) |
  1151. Q(description__icontains=value)
  1152. )
  1153. return queryset.filter(qs_filter)
  1154. @register_filterset
  1155. class DeviceRoleFilterSet(NestedGroupModelFilterSet):
  1156. config_template_id = django_filters.ModelMultipleChoiceFilter(
  1157. queryset=ConfigTemplate.objects.all(),
  1158. distinct=False,
  1159. label=_('Config template (ID)'),
  1160. )
  1161. parent_id = django_filters.ModelMultipleChoiceFilter(
  1162. queryset=DeviceRole.objects.all(),
  1163. distinct=False,
  1164. label=_('Parent device role (ID)'),
  1165. )
  1166. parent = django_filters.ModelMultipleChoiceFilter(
  1167. field_name='parent__slug',
  1168. queryset=DeviceRole.objects.all(),
  1169. distinct=False,
  1170. to_field_name='slug',
  1171. label=_('Parent device role (slug)'),
  1172. )
  1173. ancestor_id = TreeNodeMultipleChoiceFilter(
  1174. queryset=DeviceRole.objects.all(),
  1175. field_name='parent',
  1176. lookup_expr='in',
  1177. label=_('Parent device role (ID)'),
  1178. )
  1179. ancestor = TreeNodeMultipleChoiceFilter(
  1180. queryset=DeviceRole.objects.all(),
  1181. field_name='parent',
  1182. lookup_expr='in',
  1183. to_field_name='slug',
  1184. label=_('Parent device role (slug)'),
  1185. )
  1186. class Meta:
  1187. model = DeviceRole
  1188. fields = ('id', 'name', 'slug', 'color', 'vm_role', 'description')
  1189. @register_filterset
  1190. class PlatformFilterSet(NestedGroupModelFilterSet):
  1191. parent_id = django_filters.ModelMultipleChoiceFilter(
  1192. queryset=Platform.objects.all(),
  1193. distinct=False,
  1194. label=_('Immediate parent platform (ID)'),
  1195. )
  1196. parent = django_filters.ModelMultipleChoiceFilter(
  1197. field_name='parent__slug',
  1198. queryset=Platform.objects.all(),
  1199. distinct=False,
  1200. to_field_name='slug',
  1201. label=_('Immediate parent platform (slug)'),
  1202. )
  1203. ancestor_id = TreeNodeMultipleChoiceFilter(
  1204. queryset=Platform.objects.all(),
  1205. field_name='parent',
  1206. lookup_expr='in',
  1207. label=_('Parent platform (ID)'),
  1208. )
  1209. ancestor = TreeNodeMultipleChoiceFilter(
  1210. queryset=Platform.objects.all(),
  1211. field_name='parent',
  1212. lookup_expr='in',
  1213. to_field_name='slug',
  1214. label=_('Parent platform (slug)'),
  1215. )
  1216. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  1217. field_name='manufacturer',
  1218. queryset=Manufacturer.objects.all(),
  1219. distinct=False,
  1220. label=_('Manufacturer (ID)'),
  1221. )
  1222. manufacturer = django_filters.ModelMultipleChoiceFilter(
  1223. field_name='manufacturer__slug',
  1224. queryset=Manufacturer.objects.all(),
  1225. distinct=False,
  1226. to_field_name='slug',
  1227. label=_('Manufacturer (slug)'),
  1228. )
  1229. available_for_device_type = django_filters.ModelChoiceFilter(
  1230. queryset=DeviceType.objects.all(),
  1231. method='get_for_device_type'
  1232. )
  1233. config_template_id = django_filters.ModelMultipleChoiceFilter(
  1234. queryset=ConfigTemplate.objects.all(),
  1235. distinct=False,
  1236. label=_('Config template (ID)'),
  1237. )
  1238. class Meta:
  1239. model = Platform
  1240. fields = ('id', 'name', 'slug', 'description')
  1241. @extend_schema_field(OpenApiTypes.STR)
  1242. def get_for_device_type(self, queryset, name, value):
  1243. """
  1244. Return all Platforms available for a specific manufacturer based on device type and Platforms not assigned any
  1245. manufacturer
  1246. """
  1247. return queryset.filter(Q(manufacturer=None) | Q(manufacturer__device_types=value))
  1248. @register_filterset
  1249. class DeviceFilterSet(
  1250. PrimaryModelFilterSet,
  1251. TenancyFilterSet,
  1252. ContactModelFilterSet,
  1253. LocalConfigContextFilterSet,
  1254. PrimaryIPFilterSet,
  1255. ):
  1256. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  1257. field_name='device_type__manufacturer',
  1258. queryset=Manufacturer.objects.all(),
  1259. distinct=False,
  1260. label=_('Manufacturer (ID)'),
  1261. )
  1262. manufacturer = django_filters.ModelMultipleChoiceFilter(
  1263. field_name='device_type__manufacturer__slug',
  1264. queryset=Manufacturer.objects.all(),
  1265. distinct=False,
  1266. to_field_name='slug',
  1267. label=_('Manufacturer (slug)'),
  1268. )
  1269. device_type = django_filters.ModelMultipleChoiceFilter(
  1270. field_name='device_type__slug',
  1271. queryset=DeviceType.objects.all(),
  1272. distinct=False,
  1273. to_field_name='slug',
  1274. label=_('Device type (slug)'),
  1275. )
  1276. device_type_id = django_filters.ModelMultipleChoiceFilter(
  1277. queryset=DeviceType.objects.all(),
  1278. distinct=False,
  1279. label=_('Device type (ID)'),
  1280. )
  1281. role_id = TreeNodeMultipleChoiceFilter(
  1282. field_name='role',
  1283. queryset=DeviceRole.objects.all(),
  1284. lookup_expr='in',
  1285. label=_('Role (ID)'),
  1286. )
  1287. role = TreeNodeMultipleChoiceFilter(
  1288. queryset=DeviceRole.objects.all(),
  1289. field_name='role',
  1290. lookup_expr='in',
  1291. to_field_name='slug',
  1292. label=_('Role (slug)'),
  1293. )
  1294. parent_device_id = django_filters.ModelMultipleChoiceFilter(
  1295. field_name='parent_bay__device',
  1296. queryset=Device.objects.all(),
  1297. label=_('Parent Device (ID)'),
  1298. )
  1299. platform_id = TreeNodeMultipleChoiceFilter(
  1300. queryset=Platform.objects.all(),
  1301. field_name='platform',
  1302. lookup_expr='in',
  1303. label=_('Platform (ID)'),
  1304. )
  1305. platform = TreeNodeMultipleChoiceFilter(
  1306. field_name='platform',
  1307. queryset=Platform.objects.all(),
  1308. to_field_name='slug',
  1309. lookup_expr='in',
  1310. label=_('Platform (slug)'),
  1311. )
  1312. region_id = TreeNodeMultipleChoiceFilter(
  1313. queryset=Region.objects.all(),
  1314. field_name='site__region',
  1315. lookup_expr='in',
  1316. label=_('Region (ID)'),
  1317. )
  1318. region = TreeNodeMultipleChoiceFilter(
  1319. queryset=Region.objects.all(),
  1320. field_name='site__region',
  1321. lookup_expr='in',
  1322. to_field_name='slug',
  1323. label=_('Region (slug)'),
  1324. )
  1325. site_group_id = TreeNodeMultipleChoiceFilter(
  1326. queryset=SiteGroup.objects.all(),
  1327. field_name='site__group',
  1328. lookup_expr='in',
  1329. label=_('Site group (ID)'),
  1330. )
  1331. site_group = TreeNodeMultipleChoiceFilter(
  1332. queryset=SiteGroup.objects.all(),
  1333. field_name='site__group',
  1334. lookup_expr='in',
  1335. to_field_name='slug',
  1336. label=_('Site group (slug)'),
  1337. )
  1338. site_id = django_filters.ModelMultipleChoiceFilter(
  1339. queryset=Site.objects.all(),
  1340. distinct=False,
  1341. label=_('Site (ID)'),
  1342. )
  1343. site = django_filters.ModelMultipleChoiceFilter(
  1344. field_name='site__slug',
  1345. queryset=Site.objects.all(),
  1346. distinct=False,
  1347. to_field_name='slug',
  1348. label=_('Site name (slug)'),
  1349. )
  1350. location_id = TreeNodeMultipleChoiceFilter(
  1351. queryset=Location.objects.all(),
  1352. field_name='location',
  1353. lookup_expr='in',
  1354. label=_('Location (ID)'),
  1355. )
  1356. location = TreeNodeMultipleChoiceFilter(
  1357. queryset=Location.objects.all(),
  1358. field_name='location',
  1359. lookup_expr='in',
  1360. to_field_name='slug',
  1361. label=_('Location (slug)'),
  1362. )
  1363. rack_id = django_filters.ModelMultipleChoiceFilter(
  1364. field_name='rack',
  1365. queryset=Rack.objects.all(),
  1366. distinct=False,
  1367. label=_('Rack (ID)'),
  1368. )
  1369. parent_bay_id = django_filters.ModelMultipleChoiceFilter(
  1370. field_name='parent_bay',
  1371. queryset=DeviceBay.objects.all(),
  1372. label=_('Parent bay (ID)'),
  1373. )
  1374. cluster_id = django_filters.ModelMultipleChoiceFilter(
  1375. queryset=Cluster.objects.all(),
  1376. distinct=False,
  1377. label=_('VM cluster (ID)'),
  1378. )
  1379. cluster_group = django_filters.ModelMultipleChoiceFilter(
  1380. field_name='cluster__group__slug',
  1381. queryset=ClusterGroup.objects.all(),
  1382. distinct=False,
  1383. to_field_name='slug',
  1384. label=_('Cluster group (slug)'),
  1385. )
  1386. cluster_group_id = django_filters.ModelMultipleChoiceFilter(
  1387. field_name='cluster__group',
  1388. queryset=ClusterGroup.objects.all(),
  1389. distinct=False,
  1390. label=_('Cluster group (ID)'),
  1391. )
  1392. model = django_filters.ModelMultipleChoiceFilter(
  1393. field_name='device_type__slug',
  1394. queryset=DeviceType.objects.all(),
  1395. distinct=False,
  1396. to_field_name='slug',
  1397. label=_('Device model (slug)'),
  1398. )
  1399. name = MultiValueCharFilter(
  1400. lookup_expr='iexact'
  1401. )
  1402. status = django_filters.MultipleChoiceFilter(
  1403. choices=DeviceStatusChoices,
  1404. distinct=False,
  1405. null_value=None
  1406. )
  1407. is_full_depth = django_filters.BooleanFilter(
  1408. field_name='device_type__is_full_depth',
  1409. label=_('Is full depth'),
  1410. )
  1411. mac_address = MultiValueMACAddressFilter(
  1412. field_name='interfaces__mac_addresses__mac_address',
  1413. label=_('MAC address'),
  1414. )
  1415. serial = MultiValueCharFilter(
  1416. lookup_expr='iexact'
  1417. )
  1418. has_primary_ip = django_filters.BooleanFilter(
  1419. method='_has_primary_ip',
  1420. label=_('Has a primary IP'),
  1421. )
  1422. has_oob_ip = django_filters.BooleanFilter(
  1423. method='_has_oob_ip',
  1424. label=_('Has an out-of-band IP'),
  1425. )
  1426. virtual_chassis_id = django_filters.ModelMultipleChoiceFilter(
  1427. field_name='virtual_chassis',
  1428. queryset=VirtualChassis.objects.all(),
  1429. distinct=False,
  1430. label=_('Virtual chassis (ID)'),
  1431. )
  1432. virtual_chassis_member = django_filters.BooleanFilter(
  1433. method='_virtual_chassis_member',
  1434. label=_('Is a virtual chassis member')
  1435. )
  1436. config_template_id = django_filters.ModelMultipleChoiceFilter(
  1437. queryset=ConfigTemplate.objects.all(),
  1438. distinct=False,
  1439. label=_('Config template (ID)'),
  1440. )
  1441. console_ports = django_filters.BooleanFilter(
  1442. method='_console_ports',
  1443. label=_('Has console ports'),
  1444. )
  1445. console_server_ports = django_filters.BooleanFilter(
  1446. method='_console_server_ports',
  1447. label=_('Has console server ports'),
  1448. )
  1449. power_ports = django_filters.BooleanFilter(
  1450. method='_power_ports',
  1451. label=_('Has power ports'),
  1452. )
  1453. power_outlets = django_filters.BooleanFilter(
  1454. method='_power_outlets',
  1455. label=_('Has power outlets'),
  1456. )
  1457. interfaces = django_filters.BooleanFilter(
  1458. method='_interfaces',
  1459. label=_('Has interfaces'),
  1460. )
  1461. pass_through_ports = django_filters.BooleanFilter(
  1462. method='_pass_through_ports',
  1463. label=_('Has pass-through ports'),
  1464. )
  1465. module_bays = django_filters.BooleanFilter(
  1466. method='_module_bays',
  1467. label=_('Has module bays'),
  1468. )
  1469. device_bays = django_filters.BooleanFilter(
  1470. method='_device_bays',
  1471. label=_('Has device bays'),
  1472. )
  1473. oob_ip_id = django_filters.ModelMultipleChoiceFilter(
  1474. field_name='oob_ip',
  1475. queryset=IPAddress.objects.all(),
  1476. distinct=False,
  1477. label=_('OOB IP (ID)'),
  1478. )
  1479. has_virtual_device_context = django_filters.BooleanFilter(
  1480. method='_has_virtual_device_context',
  1481. label=_('Has virtual device context'),
  1482. )
  1483. class Meta:
  1484. model = Device
  1485. fields = (
  1486. 'id', 'asset_tag', 'face', 'position', 'latitude', 'longitude', 'airflow', 'cooling_method', 'vc_position',
  1487. 'vc_priority', 'description',
  1488. # Counters
  1489. 'console_port_count',
  1490. 'console_server_port_count',
  1491. 'power_port_count',
  1492. 'power_outlet_count',
  1493. 'cooling_intake_count',
  1494. 'cooling_outflow_count',
  1495. 'interface_count',
  1496. 'front_port_count',
  1497. 'rear_port_count',
  1498. 'device_bay_count',
  1499. 'module_bay_count',
  1500. 'inventory_item_count',
  1501. )
  1502. def search(self, queryset, name, value):
  1503. if not value.strip():
  1504. return queryset
  1505. qs_filter = (
  1506. Q(name__icontains=value) |
  1507. Q(virtual_chassis__name__icontains=value) |
  1508. Q(serial__icontains=value.strip()) |
  1509. Q(asset_tag__icontains=value.strip()) |
  1510. Q(description__icontains=value.strip()) |
  1511. Q(comments__icontains=value)
  1512. )
  1513. # If the given value looks like an IP address, look for primary IPv4/IPv6 assignments
  1514. try:
  1515. ipaddress = netaddr.IPNetwork(value)
  1516. if ipaddress.version == 4:
  1517. qs_filter |= Q(primary_ip4__address__host__inet=ipaddress.ip)
  1518. elif ipaddress.version == 6:
  1519. qs_filter |= Q(primary_ip6__address__host__inet=ipaddress.ip)
  1520. except (AddrFormatError, ValueError):
  1521. pass
  1522. return queryset.filter(qs_filter)
  1523. def _has_primary_ip(self, queryset, name, value):
  1524. params = Q(primary_ip4__isnull=False) | Q(primary_ip6__isnull=False)
  1525. if value:
  1526. return queryset.filter(params)
  1527. return queryset.exclude(params)
  1528. def _has_oob_ip(self, queryset, name, value):
  1529. params = Q(oob_ip__isnull=False)
  1530. if value:
  1531. return queryset.filter(params)
  1532. return queryset.exclude(params)
  1533. def _virtual_chassis_member(self, queryset, name, value):
  1534. return queryset.exclude(virtual_chassis__isnull=value)
  1535. def _console_ports(self, queryset, name, value):
  1536. return queryset.exclude(consoleports__isnull=value)
  1537. def _console_server_ports(self, queryset, name, value):
  1538. return queryset.exclude(consoleserverports__isnull=value)
  1539. def _power_ports(self, queryset, name, value):
  1540. return queryset.exclude(powerports__isnull=value)
  1541. def _power_outlets(self, queryset, name, value):
  1542. return queryset.exclude(poweroutlets__isnull=value)
  1543. def _interfaces(self, queryset, name, value):
  1544. return queryset.exclude(interfaces__isnull=value)
  1545. def _pass_through_ports(self, queryset, name, value):
  1546. return queryset.exclude(
  1547. frontports__isnull=value,
  1548. rearports__isnull=value
  1549. )
  1550. def _module_bays(self, queryset, name, value):
  1551. return queryset.exclude(modulebays__isnull=value)
  1552. def _device_bays(self, queryset, name, value):
  1553. return queryset.exclude(devicebays__isnull=value)
  1554. def _has_virtual_device_context(self, queryset, name, value):
  1555. params = Q(vdcs__isnull=False)
  1556. if value:
  1557. return queryset.filter(params).distinct()
  1558. return queryset.exclude(params)
  1559. @register_filterset
  1560. class VirtualDeviceContextFilterSet(PrimaryModelFilterSet, TenancyFilterSet, PrimaryIPFilterSet):
  1561. device_id = django_filters.ModelMultipleChoiceFilter(
  1562. field_name='device',
  1563. queryset=Device.objects.all(),
  1564. distinct=False,
  1565. label=_('VDC (ID)')
  1566. )
  1567. device = django_filters.ModelMultipleChoiceFilter(
  1568. field_name='device',
  1569. queryset=Device.objects.all(),
  1570. distinct=False,
  1571. label=_('Device model')
  1572. )
  1573. interface_id = django_filters.ModelMultipleChoiceFilter(
  1574. field_name='interfaces',
  1575. queryset=Interface.objects.all(),
  1576. label=_('Interface (ID)')
  1577. )
  1578. status = django_filters.MultipleChoiceFilter(
  1579. choices=VirtualDeviceContextStatusChoices,
  1580. distinct=False,
  1581. )
  1582. has_primary_ip = django_filters.BooleanFilter(
  1583. method='_has_primary_ip',
  1584. label=_('Has a primary IP')
  1585. )
  1586. class Meta:
  1587. model = VirtualDeviceContext
  1588. fields = ('id', 'device', 'name', 'identifier', 'description')
  1589. def search(self, queryset, name, value):
  1590. if not value.strip():
  1591. return queryset
  1592. qs_filter = (
  1593. Q(name__icontains=value) |
  1594. Q(description__icontains=value)
  1595. )
  1596. try:
  1597. qs_filter |= Q(identifier=int(value))
  1598. except ValueError:
  1599. pass
  1600. return queryset.filter(qs_filter).distinct()
  1601. def _has_primary_ip(self, queryset, name, value):
  1602. params = Q(primary_ip4__isnull=False) | Q(primary_ip6__isnull=False)
  1603. if value:
  1604. return queryset.filter(params)
  1605. return queryset.exclude(params)
  1606. @register_filterset
  1607. class ModuleFilterSet(PrimaryModelFilterSet):
  1608. profile_id = django_filters.ModelMultipleChoiceFilter(
  1609. field_name='module_type__profile',
  1610. queryset=ModuleTypeProfile.objects.all(),
  1611. distinct=False,
  1612. label=_('Profile (ID)'),
  1613. )
  1614. profile = django_filters.ModelMultipleChoiceFilter(
  1615. field_name='module_type__profile__name',
  1616. queryset=ModuleTypeProfile.objects.all(),
  1617. distinct=False,
  1618. to_field_name='name',
  1619. label=_('Profile (name)'),
  1620. )
  1621. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  1622. field_name='module_type__manufacturer',
  1623. queryset=Manufacturer.objects.all(),
  1624. distinct=False,
  1625. label=_('Manufacturer (ID)'),
  1626. )
  1627. manufacturer = django_filters.ModelMultipleChoiceFilter(
  1628. field_name='module_type__manufacturer__slug',
  1629. queryset=Manufacturer.objects.all(),
  1630. distinct=False,
  1631. to_field_name='slug',
  1632. label=_('Manufacturer (slug)'),
  1633. )
  1634. module_type_id = django_filters.ModelMultipleChoiceFilter(
  1635. field_name='module_type',
  1636. queryset=ModuleType.objects.all(),
  1637. distinct=False,
  1638. label=_('Module type (ID)'),
  1639. )
  1640. module_type = django_filters.ModelMultipleChoiceFilter(
  1641. field_name='module_type__model',
  1642. queryset=ModuleType.objects.all(),
  1643. distinct=False,
  1644. to_field_name='model',
  1645. label=_('Module type (model)'),
  1646. )
  1647. module_bay_id = TreeNodeMultipleChoiceFilter(
  1648. queryset=ModuleBay.objects.all(),
  1649. field_name='module_bay',
  1650. lookup_expr='in',
  1651. label=_('Module bay (ID)'),
  1652. )
  1653. region_id = TreeNodeMultipleChoiceFilter(
  1654. queryset=Region.objects.all(),
  1655. field_name='device__site__region',
  1656. lookup_expr='in',
  1657. label=_('Region (ID)'),
  1658. )
  1659. region = TreeNodeMultipleChoiceFilter(
  1660. queryset=Region.objects.all(),
  1661. field_name='device__site__region',
  1662. lookup_expr='in',
  1663. to_field_name='slug',
  1664. label=_('Region (slug)'),
  1665. )
  1666. site_group_id = TreeNodeMultipleChoiceFilter(
  1667. queryset=SiteGroup.objects.all(),
  1668. field_name='device__site__group',
  1669. lookup_expr='in',
  1670. label=_('Site group (ID)'),
  1671. )
  1672. site_group = TreeNodeMultipleChoiceFilter(
  1673. queryset=SiteGroup.objects.all(),
  1674. field_name='device__site__group',
  1675. lookup_expr='in',
  1676. to_field_name='slug',
  1677. label=_('Site group (slug)'),
  1678. )
  1679. site_id = django_filters.ModelMultipleChoiceFilter(
  1680. field_name='device__site',
  1681. queryset=Site.objects.all(),
  1682. distinct=False,
  1683. label=_('Site (ID)'),
  1684. )
  1685. site = django_filters.ModelMultipleChoiceFilter(
  1686. field_name='device__site__slug',
  1687. queryset=Site.objects.all(),
  1688. distinct=False,
  1689. to_field_name='slug',
  1690. label=_('Site name (slug)'),
  1691. )
  1692. location_id = django_filters.ModelMultipleChoiceFilter(
  1693. field_name='device__location',
  1694. queryset=Location.objects.all(),
  1695. distinct=False,
  1696. label=_('Location (ID)'),
  1697. )
  1698. location = django_filters.ModelMultipleChoiceFilter(
  1699. field_name='device__location__slug',
  1700. queryset=Location.objects.all(),
  1701. distinct=False,
  1702. to_field_name='slug',
  1703. label=_('Location (slug)'),
  1704. )
  1705. rack_id = django_filters.ModelMultipleChoiceFilter(
  1706. field_name='device__rack',
  1707. queryset=Rack.objects.all(),
  1708. distinct=False,
  1709. label=_('Rack (ID)'),
  1710. )
  1711. rack = django_filters.ModelMultipleChoiceFilter(
  1712. field_name='device__rack__name',
  1713. queryset=Rack.objects.all(),
  1714. distinct=False,
  1715. to_field_name='name',
  1716. label=_('Rack (name)'),
  1717. )
  1718. device_id = django_filters.ModelMultipleChoiceFilter(
  1719. queryset=Device.objects.all(),
  1720. distinct=False,
  1721. label=_('Device (ID)'),
  1722. )
  1723. device = django_filters.ModelMultipleChoiceFilter(
  1724. field_name='device__name',
  1725. queryset=Device.objects.all(),
  1726. distinct=False,
  1727. to_field_name='name',
  1728. label=_('Device (name)'),
  1729. )
  1730. status = django_filters.MultipleChoiceFilter(
  1731. choices=ModuleStatusChoices,
  1732. distinct=False,
  1733. null_value=None
  1734. )
  1735. serial = MultiValueCharFilter(
  1736. lookup_expr='iexact'
  1737. )
  1738. class Meta:
  1739. model = Module
  1740. fields = ('id', 'status', 'asset_tag', 'description')
  1741. def search(self, queryset, name, value):
  1742. if not value.strip():
  1743. return queryset
  1744. return queryset.filter(
  1745. Q(device__name__icontains=value.strip()) |
  1746. Q(serial__icontains=value.strip()) |
  1747. Q(asset_tag__icontains=value.strip()) |
  1748. Q(description__icontains=value) |
  1749. Q(comments__icontains=value)
  1750. ).distinct()
  1751. class DeviceComponentFilterSet(OwnerFilterMixin, NetBoxModelFilterSet):
  1752. q = django_filters.CharFilter(
  1753. method='search',
  1754. label=_('Search'),
  1755. )
  1756. region_id = TreeNodeMultipleChoiceFilter(
  1757. queryset=Region.objects.all(),
  1758. field_name='device__site__region',
  1759. lookup_expr='in',
  1760. label=_('Region (ID)'),
  1761. )
  1762. region = TreeNodeMultipleChoiceFilter(
  1763. queryset=Region.objects.all(),
  1764. field_name='device__site__region',
  1765. lookup_expr='in',
  1766. to_field_name='slug',
  1767. label=_('Region (slug)'),
  1768. )
  1769. site_group_id = TreeNodeMultipleChoiceFilter(
  1770. queryset=SiteGroup.objects.all(),
  1771. field_name='device__site__group',
  1772. lookup_expr='in',
  1773. label=_('Site group (ID)'),
  1774. )
  1775. site_group = TreeNodeMultipleChoiceFilter(
  1776. queryset=SiteGroup.objects.all(),
  1777. field_name='device__site__group',
  1778. lookup_expr='in',
  1779. to_field_name='slug',
  1780. label=_('Site group (slug)'),
  1781. )
  1782. site_id = django_filters.ModelMultipleChoiceFilter(
  1783. field_name='_site',
  1784. queryset=Site.objects.all(),
  1785. distinct=False,
  1786. label=_('Site (ID)'),
  1787. )
  1788. site = django_filters.ModelMultipleChoiceFilter(
  1789. field_name='_site__slug',
  1790. queryset=Site.objects.all(),
  1791. distinct=False,
  1792. to_field_name='slug',
  1793. label=_('Site name (slug)'),
  1794. )
  1795. location_id = django_filters.ModelMultipleChoiceFilter(
  1796. field_name='_location',
  1797. queryset=Location.objects.all(),
  1798. distinct=False,
  1799. label=_('Location (ID)'),
  1800. )
  1801. location = django_filters.ModelMultipleChoiceFilter(
  1802. field_name='_location__slug',
  1803. queryset=Location.objects.all(),
  1804. distinct=False,
  1805. to_field_name='slug',
  1806. label=_('Location (slug)'),
  1807. )
  1808. rack_id = django_filters.ModelMultipleChoiceFilter(
  1809. field_name='_rack',
  1810. queryset=Rack.objects.all(),
  1811. distinct=False,
  1812. label=_('Rack (ID)'),
  1813. )
  1814. rack = django_filters.ModelMultipleChoiceFilter(
  1815. field_name='_rack__name',
  1816. queryset=Rack.objects.all(),
  1817. distinct=False,
  1818. to_field_name='name',
  1819. label=_('Rack (name)'),
  1820. )
  1821. device_id = django_filters.ModelMultipleChoiceFilter(
  1822. queryset=Device.objects.all(),
  1823. distinct=False,
  1824. label=_('Device (ID)'),
  1825. )
  1826. device = django_filters.ModelMultipleChoiceFilter(
  1827. field_name='device__name',
  1828. queryset=Device.objects.all(),
  1829. distinct=False,
  1830. to_field_name='name',
  1831. label=_('Device (name)'),
  1832. )
  1833. device_type_id = django_filters.ModelMultipleChoiceFilter(
  1834. field_name='device__device_type',
  1835. queryset=DeviceType.objects.all(),
  1836. distinct=False,
  1837. label=_('Device type (ID)'),
  1838. )
  1839. device_type = django_filters.ModelMultipleChoiceFilter(
  1840. field_name='device__device_type__model',
  1841. queryset=DeviceType.objects.all(),
  1842. distinct=False,
  1843. to_field_name='model',
  1844. label=_('Device type (model)'),
  1845. )
  1846. device_role_id = django_filters.ModelMultipleChoiceFilter(
  1847. field_name='device__role',
  1848. queryset=DeviceRole.objects.all(),
  1849. distinct=False,
  1850. label=_('Device role (ID)'),
  1851. )
  1852. device_role = django_filters.ModelMultipleChoiceFilter(
  1853. field_name='device__role__slug',
  1854. queryset=DeviceRole.objects.all(),
  1855. distinct=False,
  1856. to_field_name='slug',
  1857. label=_('Device role (slug)'),
  1858. )
  1859. virtual_chassis_id = django_filters.ModelMultipleChoiceFilter(
  1860. field_name='device__virtual_chassis',
  1861. queryset=VirtualChassis.objects.all(),
  1862. distinct=False,
  1863. label=_('Virtual Chassis (ID)')
  1864. )
  1865. virtual_chassis = django_filters.ModelMultipleChoiceFilter(
  1866. field_name='device__virtual_chassis__name',
  1867. queryset=VirtualChassis.objects.all(),
  1868. distinct=False,
  1869. to_field_name='name',
  1870. label=_('Virtual Chassis'),
  1871. )
  1872. device_status = django_filters.MultipleChoiceFilter(
  1873. choices=DeviceStatusChoices,
  1874. distinct=False,
  1875. field_name='device__status',
  1876. )
  1877. tenant_id = django_filters.ModelMultipleChoiceFilter(
  1878. field_name='device__tenant',
  1879. queryset=Tenant.objects.all(),
  1880. distinct=False,
  1881. label=_('Tenant (ID)'),
  1882. )
  1883. tenant = django_filters.ModelMultipleChoiceFilter(
  1884. field_name='device__tenant__slug',
  1885. queryset=Tenant.objects.all(),
  1886. distinct=False,
  1887. to_field_name='slug',
  1888. label=_('Tenant (slug)'),
  1889. )
  1890. def search(self, queryset, name, value):
  1891. if not value.strip():
  1892. return queryset
  1893. return queryset.filter(
  1894. Q(name__icontains=value) |
  1895. Q(label__icontains=value) |
  1896. Q(description__icontains=value)
  1897. )
  1898. class ModularDeviceComponentFilterSet(DeviceComponentFilterSet):
  1899. """
  1900. Extends DeviceComponentFilterSet to add a module_id filter for components
  1901. which can be associated with a particular module within a device.
  1902. """
  1903. module_id = django_filters.ModelMultipleChoiceFilter(
  1904. queryset=Module.objects.all(),
  1905. distinct=False,
  1906. label=_('Module (ID)'),
  1907. )
  1908. class CabledObjectFilterSet(django_filters.FilterSet):
  1909. cable_id = django_filters.ModelMultipleChoiceFilter(
  1910. queryset=Cable.objects.all(),
  1911. distinct=False,
  1912. label=_('Cable (ID)'),
  1913. )
  1914. cabled = django_filters.BooleanFilter(
  1915. field_name='cable',
  1916. lookup_expr='isnull',
  1917. exclude=True
  1918. )
  1919. occupied = django_filters.BooleanFilter(
  1920. method='filter_occupied'
  1921. )
  1922. def filter_occupied(self, queryset, name, value):
  1923. if value:
  1924. return queryset.filter(Q(cable__isnull=False) | Q(mark_connected=True))
  1925. return queryset.filter(cable__isnull=True, mark_connected=False)
  1926. class PathEndpointFilterSet(django_filters.FilterSet):
  1927. connected = django_filters.BooleanFilter(
  1928. method='filter_connected'
  1929. )
  1930. def filter_connected(self, queryset, name, value):
  1931. if value:
  1932. return queryset.filter(_path__is_active=True, _path__is_complete=True)
  1933. return queryset.filter(Q(_path__isnull=True) | Q(_path__is_active=False) | Q(_path__is_complete=False))
  1934. @register_filterset
  1935. class ConsolePortFilterSet(ModularDeviceComponentFilterSet, CabledObjectFilterSet, PathEndpointFilterSet):
  1936. type = django_filters.MultipleChoiceFilter(
  1937. choices=ConsolePortTypeChoices,
  1938. distinct=False,
  1939. null_value=None
  1940. )
  1941. class Meta:
  1942. model = ConsolePort
  1943. fields = (
  1944. 'id', 'name', 'label', 'speed', 'description', 'mark_connected', 'cable_end', 'cable_connector',
  1945. )
  1946. @register_filterset
  1947. class ConsoleServerPortFilterSet(ModularDeviceComponentFilterSet, CabledObjectFilterSet, PathEndpointFilterSet):
  1948. type = django_filters.MultipleChoiceFilter(
  1949. choices=ConsolePortTypeChoices,
  1950. distinct=False,
  1951. null_value=None
  1952. )
  1953. class Meta:
  1954. model = ConsoleServerPort
  1955. fields = (
  1956. 'id', 'name', 'label', 'speed', 'description', 'mark_connected', 'cable_end', 'cable_connector',
  1957. )
  1958. @register_filterset
  1959. class PowerPortFilterSet(ModularDeviceComponentFilterSet, CabledObjectFilterSet, PathEndpointFilterSet):
  1960. type = django_filters.MultipleChoiceFilter(
  1961. choices=PowerPortTypeChoices,
  1962. distinct=False,
  1963. null_value=None
  1964. )
  1965. class Meta:
  1966. model = PowerPort
  1967. fields = (
  1968. 'id', 'name', 'label', 'maximum_draw', 'allocated_draw', 'description', 'mark_connected', 'cable_end',
  1969. 'cable_connector',
  1970. )
  1971. @register_filterset
  1972. class PowerOutletFilterSet(ModularDeviceComponentFilterSet, CabledObjectFilterSet, PathEndpointFilterSet):
  1973. type = django_filters.MultipleChoiceFilter(
  1974. choices=PowerOutletTypeChoices,
  1975. distinct=False,
  1976. null_value=None
  1977. )
  1978. feed_leg = django_filters.MultipleChoiceFilter(
  1979. choices=PowerOutletFeedLegChoices,
  1980. distinct=False,
  1981. null_value=None
  1982. )
  1983. power_port_id = django_filters.ModelMultipleChoiceFilter(
  1984. queryset=PowerPort.objects.all(),
  1985. distinct=False,
  1986. label=_('Power port (ID)'),
  1987. )
  1988. status = django_filters.MultipleChoiceFilter(
  1989. choices=PowerOutletStatusChoices,
  1990. distinct=False,
  1991. null_value=None
  1992. )
  1993. class Meta:
  1994. model = PowerOutlet
  1995. fields = (
  1996. 'id', 'name', 'status', 'label', 'feed_leg', 'description', 'color', 'mark_connected', 'cable_end',
  1997. 'cable_connector',
  1998. )
  1999. @register_filterset
  2000. class CoolingIntakeFilterSet(ModularDeviceComponentFilterSet):
  2001. type = django_filters.MultipleChoiceFilter(
  2002. choices=CoolingConnectorTypeChoices,
  2003. distinct=False,
  2004. null_value=None
  2005. )
  2006. diameter_unit = django_filters.MultipleChoiceFilter(
  2007. choices=DiameterUnitChoices,
  2008. distinct=False,
  2009. null_value=None
  2010. )
  2011. max_flow_unit = django_filters.MultipleChoiceFilter(
  2012. choices=FlowRateUnitChoices,
  2013. distinct=False,
  2014. null_value=None
  2015. )
  2016. cooling_outflow_id = django_filters.ModelMultipleChoiceFilter(
  2017. queryset=CoolingOutflow.objects.all(),
  2018. field_name='cooling_outflow',
  2019. distinct=False,
  2020. label=_('Cooling outflow (ID)'),
  2021. )
  2022. class Meta:
  2023. model = CoolingIntake
  2024. fields = (
  2025. 'id', 'name', 'label', 'diameter', 'max_flow', 'description',
  2026. )
  2027. @register_filterset
  2028. class CoolingOutflowFilterSet(ModularDeviceComponentFilterSet):
  2029. type = django_filters.MultipleChoiceFilter(
  2030. choices=CoolingConnectorTypeChoices,
  2031. distinct=False,
  2032. null_value=None
  2033. )
  2034. diameter_unit = django_filters.MultipleChoiceFilter(
  2035. choices=DiameterUnitChoices,
  2036. distinct=False,
  2037. null_value=None
  2038. )
  2039. cooling_intake_id = django_filters.ModelMultipleChoiceFilter(
  2040. field_name='cooling_intake',
  2041. queryset=CoolingIntake.objects.all(),
  2042. distinct=False,
  2043. label=_('Cooling intake (ID)'),
  2044. )
  2045. class Meta:
  2046. model = CoolingOutflow
  2047. fields = (
  2048. 'id', 'name', 'label', 'diameter', 'description',
  2049. )
  2050. @register_filterset
  2051. class MACAddressFilterSet(PrimaryModelFilterSet):
  2052. mac_address = MultiValueMACAddressFilter()
  2053. assigned_object_type = MultiValueContentTypeFilter()
  2054. device = MultiValueCharFilter(
  2055. method='filter_device',
  2056. field_name='name',
  2057. label=_('Device (name)'),
  2058. )
  2059. device_id = MultiValueNumberFilter(
  2060. method='filter_device',
  2061. field_name='pk',
  2062. label=_('Device (ID)'),
  2063. )
  2064. virtual_machine = MultiValueCharFilter(
  2065. method='filter_virtual_machine',
  2066. field_name='name',
  2067. label=_('Virtual machine (name)'),
  2068. )
  2069. virtual_machine_id = MultiValueNumberFilter(
  2070. method='filter_virtual_machine',
  2071. field_name='pk',
  2072. label=_('Virtual machine (ID)'),
  2073. )
  2074. interface = django_filters.ModelMultipleChoiceFilter(
  2075. field_name='interface__name',
  2076. queryset=Interface.objects.all(),
  2077. to_field_name='name',
  2078. label=_('Interface (name)'),
  2079. )
  2080. interface_id = django_filters.ModelMultipleChoiceFilter(
  2081. field_name='interface',
  2082. queryset=Interface.objects.all(),
  2083. label=_('Interface (ID)'),
  2084. )
  2085. vminterface = django_filters.ModelMultipleChoiceFilter(
  2086. field_name='vminterface__name',
  2087. queryset=VMInterface.objects.all(),
  2088. to_field_name='name',
  2089. label=_('VM interface (name)'),
  2090. )
  2091. vminterface_id = django_filters.ModelMultipleChoiceFilter(
  2092. field_name='vminterface',
  2093. queryset=VMInterface.objects.all(),
  2094. label=_('VM interface (ID)'),
  2095. )
  2096. assigned = django_filters.BooleanFilter(
  2097. method='filter_assigned',
  2098. label=_('Is assigned'),
  2099. )
  2100. primary = django_filters.BooleanFilter(
  2101. method='filter_primary',
  2102. label=_('Is primary'),
  2103. )
  2104. class Meta:
  2105. model = MACAddress
  2106. fields = ('id', 'description', 'assigned_object_type', 'assigned_object_id')
  2107. def search(self, queryset, name, value):
  2108. if not value.strip():
  2109. return queryset
  2110. qs_filter = (
  2111. Q(mac_address__icontains=value) |
  2112. Q(description__icontains=value)
  2113. )
  2114. return queryset.filter(qs_filter)
  2115. def filter_device(self, queryset, name, value):
  2116. devices = Device.objects.filter(**{f'{name}__in': value})
  2117. if not devices.exists():
  2118. return queryset.none()
  2119. interface_ids = []
  2120. for device in devices:
  2121. interface_ids.extend(device.vc_interfaces().values_list('id', flat=True))
  2122. return queryset.filter(
  2123. interface__in=interface_ids
  2124. )
  2125. def filter_virtual_machine(self, queryset, name, value):
  2126. virtual_machines = VirtualMachine.objects.filter(**{f'{name}__in': value})
  2127. if not virtual_machines.exists():
  2128. return queryset.none()
  2129. interface_ids = []
  2130. for vm in virtual_machines:
  2131. interface_ids.extend(vm.interfaces.values_list('id', flat=True))
  2132. return queryset.filter(
  2133. vminterface__in=interface_ids
  2134. )
  2135. def filter_assigned(self, queryset, name, value):
  2136. params = {
  2137. 'assigned_object_type__isnull': True,
  2138. 'assigned_object_id__isnull': True,
  2139. }
  2140. if value:
  2141. return queryset.exclude(**params)
  2142. return queryset.filter(**params)
  2143. def filter_primary(self, queryset, name, value):
  2144. interface_mac_ids = Interface.objects.filter(primary_mac_address_id__isnull=False).values_list(
  2145. 'primary_mac_address_id', flat=True
  2146. )
  2147. vminterface_mac_ids = VMInterface.objects.filter(primary_mac_address_id__isnull=False).values_list(
  2148. 'primary_mac_address_id', flat=True
  2149. )
  2150. query = Q(pk__in=interface_mac_ids) | Q(pk__in=vminterface_mac_ids)
  2151. if value:
  2152. return queryset.filter(query)
  2153. return queryset.exclude(query)
  2154. class CommonInterfaceFilterSet(django_filters.FilterSet):
  2155. mode = django_filters.MultipleChoiceFilter(
  2156. choices=InterfaceModeChoices,
  2157. distinct=False,
  2158. label=_('802.1Q Mode')
  2159. )
  2160. vlan_id = django_filters.CharFilter(
  2161. method='filter_vlan_id',
  2162. label=_('Assigned VLAN')
  2163. )
  2164. vlan = django_filters.CharFilter(
  2165. method='filter_vlan',
  2166. label=_('Assigned VID')
  2167. )
  2168. vrf_id = django_filters.ModelMultipleChoiceFilter(
  2169. field_name='vrf',
  2170. queryset=VRF.objects.all(),
  2171. distinct=False,
  2172. label=_('VRF'),
  2173. )
  2174. vrf = django_filters.ModelMultipleChoiceFilter(
  2175. field_name='vrf__rd',
  2176. queryset=VRF.objects.all(),
  2177. distinct=False,
  2178. to_field_name='rd',
  2179. label=_('VRF (RD)'),
  2180. )
  2181. l2vpn_id = django_filters.ModelMultipleChoiceFilter(
  2182. field_name='l2vpn_terminations__l2vpn',
  2183. queryset=L2VPN.objects.all(),
  2184. label=_('L2VPN (ID)'),
  2185. )
  2186. l2vpn = django_filters.ModelMultipleChoiceFilter(
  2187. field_name='l2vpn_terminations__l2vpn__identifier',
  2188. queryset=L2VPN.objects.all(),
  2189. to_field_name='identifier',
  2190. label=_('L2VPN'),
  2191. )
  2192. vlan_translation_policy_id = django_filters.ModelMultipleChoiceFilter(
  2193. field_name='vlan_translation_policy',
  2194. queryset=VLANTranslationPolicy.objects.all(),
  2195. distinct=False,
  2196. label=_('VLAN Translation Policy (ID)'),
  2197. )
  2198. vlan_translation_policy = django_filters.ModelMultipleChoiceFilter(
  2199. field_name='vlan_translation_policy__name',
  2200. queryset=VLANTranslationPolicy.objects.all(),
  2201. distinct=False,
  2202. to_field_name='name',
  2203. label=_('VLAN Translation Policy'),
  2204. )
  2205. def filter_vlan_id(self, queryset, name, value):
  2206. value = value.strip()
  2207. if not value:
  2208. return queryset
  2209. return queryset.filter(
  2210. Q(untagged_vlan_id=value) |
  2211. Q(tagged_vlans=value) |
  2212. Q(qinq_svlan=value)
  2213. )
  2214. def filter_vlan(self, queryset, name, value):
  2215. value = value.strip()
  2216. if not value:
  2217. return queryset
  2218. return queryset.filter(
  2219. Q(untagged_vlan_id__vid=value) |
  2220. Q(tagged_vlans__vid=value) |
  2221. Q(qinq_svlan__vid=value)
  2222. )
  2223. @register_filterset
  2224. class InterfaceFilterSet(
  2225. ModularDeviceComponentFilterSet,
  2226. CabledObjectFilterSet,
  2227. PathEndpointFilterSet,
  2228. CommonInterfaceFilterSet
  2229. ):
  2230. virtual_chassis_member_or_master = MultiValueCharFilter(
  2231. method='filter_virtual_chassis_member_or_master',
  2232. field_name='name',
  2233. label=_('Virtual Chassis Interfaces for Device when device is master')
  2234. )
  2235. virtual_chassis_member_or_master_id = MultiValueNumberFilter(
  2236. method='filter_virtual_chassis_member_or_master',
  2237. field_name='pk',
  2238. label=_('Virtual Chassis Interfaces for Device when device is master (ID)')
  2239. )
  2240. virtual_chassis_member = MultiValueCharFilter(
  2241. method='filter_virtual_chassis_member',
  2242. field_name='name',
  2243. label=_('Virtual Chassis Interfaces for Device')
  2244. )
  2245. virtual_chassis_member_id = MultiValueNumberFilter(
  2246. method='filter_virtual_chassis_member',
  2247. field_name='pk',
  2248. label=_('Virtual Chassis Interfaces for Device (ID)')
  2249. )
  2250. kind = django_filters.CharFilter(
  2251. method='filter_kind',
  2252. label=_('Kind of interface'),
  2253. )
  2254. parent_id = django_filters.ModelMultipleChoiceFilter(
  2255. field_name='parent',
  2256. queryset=Interface.objects.all(),
  2257. distinct=False,
  2258. label=_('Parent interface (ID)'),
  2259. )
  2260. bridge_id = django_filters.ModelMultipleChoiceFilter(
  2261. field_name='bridge',
  2262. queryset=Interface.objects.all(),
  2263. distinct=False,
  2264. label=_('Bridged interface (ID)'),
  2265. )
  2266. lag_id = django_filters.ModelMultipleChoiceFilter(
  2267. field_name='lag',
  2268. queryset=Interface.objects.all(),
  2269. distinct=False,
  2270. label=_('LAG interface (ID)'),
  2271. )
  2272. speed = MultiValueBigNumberFilter(min_value=0)
  2273. duplex = django_filters.MultipleChoiceFilter(
  2274. choices=InterfaceDuplexChoices,
  2275. distinct=False,
  2276. )
  2277. mac_address = MultiValueMACAddressFilter(
  2278. field_name='mac_addresses__mac_address',
  2279. label=_('MAC Address')
  2280. )
  2281. primary_mac_address_id = django_filters.ModelMultipleChoiceFilter(
  2282. field_name='primary_mac_address',
  2283. queryset=MACAddress.objects.all(),
  2284. distinct=False,
  2285. label=_('Primary MAC address (ID)'),
  2286. )
  2287. primary_mac_address = django_filters.ModelMultipleChoiceFilter(
  2288. field_name='primary_mac_address__mac_address',
  2289. queryset=MACAddress.objects.all(),
  2290. distinct=False,
  2291. to_field_name='mac_address',
  2292. label=_('Primary MAC address'),
  2293. )
  2294. wwn = MultiValueWWNFilter()
  2295. poe_mode = django_filters.MultipleChoiceFilter(
  2296. choices=InterfacePoEModeChoices,
  2297. distinct=False,
  2298. )
  2299. poe_type = django_filters.MultipleChoiceFilter(
  2300. choices=InterfacePoETypeChoices,
  2301. distinct=False,
  2302. )
  2303. type = django_filters.MultipleChoiceFilter(
  2304. choices=InterfaceTypeChoices,
  2305. distinct=False,
  2306. null_value=None
  2307. )
  2308. rf_role = django_filters.MultipleChoiceFilter(
  2309. choices=WirelessRoleChoices,
  2310. distinct=False,
  2311. )
  2312. rf_channel = django_filters.MultipleChoiceFilter(
  2313. choices=WirelessChannelChoices,
  2314. distinct=False,
  2315. )
  2316. vdc_id = django_filters.ModelMultipleChoiceFilter(
  2317. field_name='vdcs',
  2318. queryset=VirtualDeviceContext.objects.all(),
  2319. label=_('Virtual Device Context')
  2320. )
  2321. vdc_identifier = django_filters.ModelMultipleChoiceFilter(
  2322. field_name='vdcs__identifier',
  2323. queryset=VirtualDeviceContext.objects.all(),
  2324. to_field_name='identifier',
  2325. label=_('Virtual Device Context (Identifier)')
  2326. )
  2327. vdc = django_filters.ModelMultipleChoiceFilter(
  2328. field_name='vdcs__name',
  2329. queryset=VirtualDeviceContext.objects.all(),
  2330. to_field_name='name',
  2331. label=_('Virtual Device Context')
  2332. )
  2333. wireless_lan_id = django_filters.ModelMultipleChoiceFilter(
  2334. field_name='wireless_lans',
  2335. queryset=WirelessLAN.objects.all(),
  2336. label=_('Wireless LAN')
  2337. )
  2338. wireless_link_id = django_filters.ModelMultipleChoiceFilter(
  2339. queryset=WirelessLink.objects.all(),
  2340. distinct=False,
  2341. label=_('Wireless link')
  2342. )
  2343. virtual_circuit_id = django_filters.ModelMultipleChoiceFilter(
  2344. field_name='virtual_circuit_termination__virtual_circuit',
  2345. queryset=VirtualCircuit.objects.all(),
  2346. label=_('Virtual circuit (ID)'),
  2347. )
  2348. virtual_circuit_termination_id = django_filters.ModelMultipleChoiceFilter(
  2349. field_name='virtual_circuit_termination',
  2350. queryset=VirtualCircuitTermination.objects.all(),
  2351. label=_('Virtual circuit termination (ID)'),
  2352. )
  2353. class Meta:
  2354. model = Interface
  2355. fields = (
  2356. 'id', 'name', 'label', 'type', 'channels', 'channel_id', 'enabled', 'mtu', 'mgmt_only', 'poe_mode',
  2357. 'poe_type', 'mode', 'rf_role', 'rf_channel', 'rf_channel_frequency', 'rf_channel_width', 'tx_power',
  2358. 'description', 'mark_connected', 'cable_id', 'cable_end', 'cable_connector',
  2359. )
  2360. def filter_virtual_chassis_member_or_master(self, queryset, name, value):
  2361. return self.filter_virtual_chassis_member(queryset, name, value, if_master=True)
  2362. def filter_virtual_chassis_member(self, queryset, name, value, if_master=False):
  2363. try:
  2364. vc_interface_ids = []
  2365. for device in Device.objects.filter(**{f'{name}__in': value}):
  2366. vc_interface_ids.extend(device.vc_interfaces(if_master=if_master).values_list('id', flat=True))
  2367. return queryset.filter(pk__in=vc_interface_ids)
  2368. except Device.DoesNotExist:
  2369. return queryset.none()
  2370. def filter_kind(self, queryset, name, value):
  2371. value = value.strip().lower()
  2372. return {
  2373. # A channel subinterface is excluded even if its type is otherwise connectable: it derives its cable
  2374. # from its channelized parent and cannot be cabled directly (matches Interface.is_wired).
  2375. 'physical': queryset.exclude(type__in=NONCONNECTABLE_IFACE_TYPES).filter(channel_id__isnull=True),
  2376. 'virtual': queryset.filter(type__in=VIRTUAL_IFACE_TYPES),
  2377. 'wireless': queryset.filter(type__in=WIRELESS_IFACE_TYPES),
  2378. }.get(value, queryset.none())
  2379. # Override the method on CabledObjectFilterSet to also check for wireless links
  2380. def filter_occupied(self, queryset, name, value):
  2381. if value:
  2382. return queryset.filter(
  2383. Q(cable__isnull=False) |
  2384. Q(wireless_link__isnull=False) |
  2385. Q(mark_connected=True)
  2386. )
  2387. return queryset.filter(
  2388. cable__isnull=True,
  2389. wireless_link__isnull=True,
  2390. mark_connected=False
  2391. )
  2392. @register_filterset
  2393. class FrontPortFilterSet(ModularDeviceComponentFilterSet, CabledObjectFilterSet):
  2394. type = django_filters.MultipleChoiceFilter(
  2395. choices=PortTypeChoices,
  2396. distinct=False,
  2397. null_value=None
  2398. )
  2399. rear_port_id = django_filters.ModelMultipleChoiceFilter(
  2400. field_name='mappings__rear_port',
  2401. queryset=RearPort.objects.all(),
  2402. to_field_name='rear_port',
  2403. label=_('Rear port (ID)'),
  2404. )
  2405. class Meta:
  2406. model = FrontPort
  2407. fields = (
  2408. 'id', 'name', 'label', 'type', 'color', 'positions', 'description', 'mark_connected', 'cable_end',
  2409. 'cable_connector',
  2410. )
  2411. @register_filterset
  2412. class RearPortFilterSet(ModularDeviceComponentFilterSet, CabledObjectFilterSet):
  2413. type = django_filters.MultipleChoiceFilter(
  2414. choices=PortTypeChoices,
  2415. distinct=False,
  2416. null_value=None
  2417. )
  2418. front_port_id = django_filters.ModelMultipleChoiceFilter(
  2419. field_name='mappings__front_port',
  2420. queryset=FrontPort.objects.all(),
  2421. to_field_name='front_port',
  2422. label=_('Front port (ID)'),
  2423. )
  2424. class Meta:
  2425. model = RearPort
  2426. fields = (
  2427. 'id', 'name', 'label', 'type', 'color', 'positions', 'description', 'mark_connected', 'cable_end',
  2428. 'cable_connector',
  2429. )
  2430. @register_filterset
  2431. class ModuleBayFilterSet(ModularDeviceComponentFilterSet):
  2432. parent_id = django_filters.ModelMultipleChoiceFilter(
  2433. queryset=ModuleBay.objects.all(),
  2434. distinct=False,
  2435. label=_('Parent module bay (ID)'),
  2436. )
  2437. installed_module_id = django_filters.ModelMultipleChoiceFilter(
  2438. field_name='installed_module',
  2439. queryset=ModuleBay.objects.all(),
  2440. label=_('Installed module (ID)'),
  2441. )
  2442. module_bay_type_id = django_filters.ModelMultipleChoiceFilter(
  2443. field_name='module_bay_types',
  2444. queryset=ModuleBayType.objects.all(),
  2445. distinct=False,
  2446. label=_('Module bay type (ID)'),
  2447. )
  2448. module_bay_type = django_filters.ModelMultipleChoiceFilter(
  2449. field_name='module_bay_types__slug',
  2450. queryset=ModuleBayType.objects.all(),
  2451. distinct=False,
  2452. to_field_name='slug',
  2453. label=_('Module bay type (slug)'),
  2454. )
  2455. class Meta:
  2456. model = ModuleBay
  2457. fields = ('id', 'name', 'label', 'position', 'enabled', 'description')
  2458. @register_filterset
  2459. class DeviceBayFilterSet(DeviceComponentFilterSet):
  2460. installed_device_id = django_filters.ModelMultipleChoiceFilter(
  2461. queryset=Device.objects.all(),
  2462. distinct=False,
  2463. label=_('Installed device (ID)'),
  2464. )
  2465. installed_device = django_filters.ModelMultipleChoiceFilter(
  2466. field_name='installed_device__name',
  2467. queryset=Device.objects.all(),
  2468. distinct=False,
  2469. to_field_name='name',
  2470. label=_('Installed device (name)'),
  2471. )
  2472. class Meta:
  2473. model = DeviceBay
  2474. fields = ('id', 'name', 'label', 'enabled', 'description')
  2475. @register_filterset
  2476. class InventoryItemFilterSet(DeviceComponentFilterSet):
  2477. parent_id = django_filters.ModelMultipleChoiceFilter(
  2478. queryset=InventoryItem.objects.all(),
  2479. distinct=False,
  2480. label=_('Parent inventory item (ID)'),
  2481. )
  2482. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  2483. queryset=Manufacturer.objects.all(),
  2484. distinct=False,
  2485. label=_('Manufacturer (ID)'),
  2486. )
  2487. manufacturer = django_filters.ModelMultipleChoiceFilter(
  2488. field_name='manufacturer__slug',
  2489. queryset=Manufacturer.objects.all(),
  2490. distinct=False,
  2491. to_field_name='slug',
  2492. label=_('Manufacturer (slug)'),
  2493. )
  2494. role_id = django_filters.ModelMultipleChoiceFilter(
  2495. queryset=InventoryItemRole.objects.all(),
  2496. distinct=False,
  2497. label=_('Role (ID)'),
  2498. )
  2499. role = django_filters.ModelMultipleChoiceFilter(
  2500. field_name='role__slug',
  2501. queryset=InventoryItemRole.objects.all(),
  2502. distinct=False,
  2503. to_field_name='slug',
  2504. label=_('Role (slug)'),
  2505. )
  2506. component_type = MultiValueContentTypeFilter()
  2507. component_id = MultiValueNumberFilter()
  2508. serial = MultiValueCharFilter(
  2509. lookup_expr='iexact'
  2510. )
  2511. status = django_filters.MultipleChoiceFilter(
  2512. choices=InventoryItemStatusChoices,
  2513. distinct=False,
  2514. null_value=None
  2515. )
  2516. class Meta:
  2517. model = InventoryItem
  2518. fields = ('id', 'name', 'label', 'part_id', 'asset_tag', 'status', 'description', 'discovered')
  2519. def search(self, queryset, name, value):
  2520. if not value.strip():
  2521. return queryset
  2522. qs_filter = (
  2523. Q(name__icontains=value) |
  2524. Q(part_id__icontains=value) |
  2525. Q(serial__icontains=value) |
  2526. Q(asset_tag__icontains=value) |
  2527. Q(description__icontains=value)
  2528. )
  2529. return queryset.filter(qs_filter)
  2530. @register_filterset
  2531. class InventoryItemRoleFilterSet(OrganizationalModelFilterSet):
  2532. class Meta:
  2533. model = InventoryItemRole
  2534. fields = ('id', 'name', 'slug', 'color', 'description')
  2535. @register_filterset
  2536. class VirtualChassisFilterSet(PrimaryModelFilterSet):
  2537. master_id = django_filters.ModelMultipleChoiceFilter(
  2538. queryset=Device.objects.all(),
  2539. distinct=False,
  2540. label=_('Master (ID)'),
  2541. )
  2542. master = django_filters.ModelMultipleChoiceFilter(
  2543. field_name='master__name',
  2544. queryset=Device.objects.all(),
  2545. distinct=False,
  2546. to_field_name='name',
  2547. label=_('Master (name)'),
  2548. )
  2549. region_id = TreeNodeMultipleChoiceFilter(
  2550. queryset=Region.objects.all(),
  2551. field_name='master__site__region',
  2552. lookup_expr='in',
  2553. label=_('Region (ID)'),
  2554. )
  2555. region = TreeNodeMultipleChoiceFilter(
  2556. queryset=Region.objects.all(),
  2557. field_name='master__site__region',
  2558. lookup_expr='in',
  2559. to_field_name='slug',
  2560. label=_('Region (slug)'),
  2561. )
  2562. site_group_id = TreeNodeMultipleChoiceFilter(
  2563. queryset=SiteGroup.objects.all(),
  2564. field_name='master__site__group',
  2565. lookup_expr='in',
  2566. label=_('Site group (ID)'),
  2567. )
  2568. site_group = TreeNodeMultipleChoiceFilter(
  2569. queryset=SiteGroup.objects.all(),
  2570. field_name='master__site__group',
  2571. lookup_expr='in',
  2572. to_field_name='slug',
  2573. label=_('Site group (slug)'),
  2574. )
  2575. site_id = django_filters.ModelMultipleChoiceFilter(
  2576. field_name='master__site',
  2577. queryset=Site.objects.all(),
  2578. distinct=False,
  2579. label=_('Site (ID)'),
  2580. )
  2581. site = django_filters.ModelMultipleChoiceFilter(
  2582. field_name='master__site__slug',
  2583. queryset=Site.objects.all(),
  2584. distinct=False,
  2585. to_field_name='slug',
  2586. label=_('Site name (slug)'),
  2587. )
  2588. tenant_id = django_filters.ModelMultipleChoiceFilter(
  2589. field_name='master__tenant',
  2590. queryset=Tenant.objects.all(),
  2591. distinct=False,
  2592. label=_('Tenant (ID)'),
  2593. )
  2594. tenant = django_filters.ModelMultipleChoiceFilter(
  2595. field_name='master__tenant__slug',
  2596. queryset=Tenant.objects.all(),
  2597. distinct=False,
  2598. to_field_name='slug',
  2599. label=_('Tenant (slug)'),
  2600. )
  2601. class Meta:
  2602. model = VirtualChassis
  2603. fields = ('id', 'domain', 'name', 'description', 'member_count')
  2604. def search(self, queryset, name, value):
  2605. if not value.strip():
  2606. return queryset
  2607. qs_filter = (
  2608. Q(name__icontains=value) |
  2609. Q(description__icontains=value) |
  2610. Q(members__name__icontains=value) |
  2611. Q(domain__icontains=value)
  2612. )
  2613. return queryset.filter(qs_filter).distinct()
  2614. @register_filterset
  2615. class CableBundleFilterSet(PrimaryModelFilterSet):
  2616. class Meta:
  2617. model = CableBundle
  2618. fields = ('id', 'name', 'description')
  2619. def search(self, queryset, name, value):
  2620. if not value.strip():
  2621. return queryset
  2622. return queryset.filter(
  2623. Q(name__icontains=value) |
  2624. Q(description__icontains=value) |
  2625. Q(comments__icontains=value)
  2626. )
  2627. @register_filterset
  2628. class CableFilterSet(TenancyFilterSet, PrimaryModelFilterSet):
  2629. termination_a_type = MultiValueContentTypeFilter(
  2630. field_name='terminations__termination_type'
  2631. )
  2632. termination_a_id = MultiValueNumberFilter(
  2633. method='filter_by_cable_end_a',
  2634. field_name='terminations__termination_id'
  2635. )
  2636. termination_b_type = MultiValueContentTypeFilter(
  2637. field_name='terminations__termination_type'
  2638. )
  2639. termination_b_id = MultiValueNumberFilter(
  2640. method='filter_by_cable_end_b',
  2641. field_name='terminations__termination_id'
  2642. )
  2643. unterminated = django_filters.BooleanFilter(
  2644. method='_unterminated',
  2645. label=_('Unterminated'),
  2646. )
  2647. bundle_id = django_filters.ModelMultipleChoiceFilter(
  2648. queryset=CableBundle.objects.all(),
  2649. label=_('Cable bundle (ID)'),
  2650. )
  2651. bundle = django_filters.ModelMultipleChoiceFilter(
  2652. field_name='bundle__name',
  2653. queryset=CableBundle.objects.all(),
  2654. to_field_name='name',
  2655. label=_('Cable bundle (name)'),
  2656. )
  2657. type = django_filters.MultipleChoiceFilter(
  2658. choices=CableTypeChoices,
  2659. distinct=False,
  2660. )
  2661. status = django_filters.MultipleChoiceFilter(
  2662. choices=LinkStatusChoices,
  2663. distinct=False,
  2664. )
  2665. profile = django_filters.MultipleChoiceFilter(
  2666. choices=CableProfileChoices,
  2667. distinct=False,
  2668. )
  2669. color = django_filters.MultipleChoiceFilter(
  2670. choices=ColorChoices,
  2671. distinct=False,
  2672. )
  2673. device_id = MultiValueNumberFilter(
  2674. method='filter_by_termination'
  2675. )
  2676. device = MultiValueCharFilter(
  2677. method='filter_by_termination',
  2678. field_name='device__name'
  2679. )
  2680. rack_id = MultiValueNumberFilter(
  2681. method='filter_by_termination',
  2682. field_name='rack_id'
  2683. )
  2684. rack = MultiValueCharFilter(
  2685. method='filter_by_termination',
  2686. field_name='rack__name'
  2687. )
  2688. location_id = MultiValueNumberFilter(
  2689. method='filter_by_termination',
  2690. field_name='location_id'
  2691. )
  2692. location = MultiValueCharFilter(
  2693. method='filter_by_termination',
  2694. field_name='location__name'
  2695. )
  2696. site_id = MultiValueNumberFilter(
  2697. method='filter_by_termination',
  2698. field_name='site_id'
  2699. )
  2700. site = MultiValueCharFilter(
  2701. method='filter_by_termination',
  2702. field_name='site__slug'
  2703. )
  2704. # Termination object filters
  2705. consoleport_id = MultiValueNumberFilter(
  2706. method='filter_by_consoleport'
  2707. )
  2708. consoleserverport_id = MultiValueNumberFilter(
  2709. method='filter_by_consoleserverport'
  2710. )
  2711. powerport_id = MultiValueNumberFilter(
  2712. method='filter_by_powerport'
  2713. )
  2714. poweroutlet_id = MultiValueNumberFilter(
  2715. method='filter_by_poweroutlet'
  2716. )
  2717. interface_id = MultiValueNumberFilter(
  2718. method='filter_by_interface'
  2719. )
  2720. frontport_id = MultiValueNumberFilter(
  2721. method='filter_by_frontport'
  2722. )
  2723. rearport_id = MultiValueNumberFilter(
  2724. method='filter_by_rearport'
  2725. )
  2726. powerfeed_id = MultiValueNumberFilter(
  2727. method='filter_by_powerfeed'
  2728. )
  2729. circuittermination_id = MultiValueNumberFilter(
  2730. method='filter_by_circuittermination'
  2731. )
  2732. class Meta:
  2733. model = Cable
  2734. fields = ('id', 'label', 'length', 'length_unit', 'description')
  2735. def search(self, queryset, name, value):
  2736. if not value.strip():
  2737. return queryset
  2738. qs_filter = (
  2739. Q(label__icontains=value) |
  2740. Q(description__icontains=value)
  2741. )
  2742. return queryset.filter(qs_filter)
  2743. def filter_by_termination(self, queryset, name, value):
  2744. # Filter by a related object cached on CableTermination. Note the underscore preceding the field name.
  2745. # Supported objects: device, rack, location, site
  2746. return queryset.filter(**{f'terminations___{name}__in': value}).distinct()
  2747. def filter_by_cable_end(self, queryset, name, value, side):
  2748. # Filter by termination id and cable_end type
  2749. return queryset.filter(**{f'{name}__in': value, 'terminations__cable_end': side}).distinct()
  2750. def filter_by_cable_end_a(self, queryset, name, value):
  2751. # Filter by termination id and cable_end type
  2752. return self.filter_by_cable_end(queryset, name, value, CableEndChoices.SIDE_A)
  2753. def filter_by_cable_end_b(self, queryset, name, value):
  2754. # Filter by termination id and cable_end type
  2755. return self.filter_by_cable_end(queryset, name, value, CableEndChoices.SIDE_B)
  2756. def _unterminated(self, queryset, name, value):
  2757. if value:
  2758. terminated_ids = (
  2759. queryset.filter(terminations__cable_end=CableEndChoices.SIDE_A)
  2760. .filter(terminations__cable_end=CableEndChoices.SIDE_B)
  2761. .values("id")
  2762. )
  2763. return queryset.exclude(id__in=terminated_ids)
  2764. return queryset.filter(terminations__cable_end=CableEndChoices.SIDE_A).filter(
  2765. terminations__cable_end=CableEndChoices.SIDE_B
  2766. )
  2767. def filter_by_termination_object(self, queryset, model, value):
  2768. # Filter by specific termination object(s)
  2769. content_type = ContentType.objects.get_for_model(model)
  2770. cable_ids = CableTermination.objects.filter(
  2771. termination_type=content_type,
  2772. termination_id__in=value
  2773. ).values_list('cable', flat=True)
  2774. return queryset.filter(pk__in=cable_ids)
  2775. def filter_by_consoleport(self, queryset, name, value):
  2776. return self.filter_by_termination_object(queryset, ConsolePort, value)
  2777. def filter_by_consoleserverport(self, queryset, name, value):
  2778. return self.filter_by_termination_object(queryset, ConsoleServerPort, value)
  2779. def filter_by_powerport(self, queryset, name, value):
  2780. return self.filter_by_termination_object(queryset, PowerPort, value)
  2781. def filter_by_poweroutlet(self, queryset, name, value):
  2782. return self.filter_by_termination_object(queryset, PowerOutlet, value)
  2783. def filter_by_interface(self, queryset, name, value):
  2784. return self.filter_by_termination_object(queryset, Interface, value)
  2785. def filter_by_frontport(self, queryset, name, value):
  2786. return self.filter_by_termination_object(queryset, FrontPort, value)
  2787. def filter_by_rearport(self, queryset, name, value):
  2788. return self.filter_by_termination_object(queryset, RearPort, value)
  2789. def filter_by_powerfeed(self, queryset, name, value):
  2790. return self.filter_by_termination_object(queryset, PowerFeed, value)
  2791. def filter_by_circuittermination(self, queryset, name, value):
  2792. return self.filter_by_termination_object(queryset, CircuitTermination, value)
  2793. @register_filterset
  2794. class CableTerminationFilterSet(ChangeLoggedModelFilterSet):
  2795. cable_id = django_filters.ModelMultipleChoiceFilter(
  2796. queryset=Cable.objects.all(),
  2797. distinct=False,
  2798. label=_('Cable (ID)'),
  2799. )
  2800. termination_type = MultiValueContentTypeFilter()
  2801. # Termination object filters
  2802. consoleport_id = MultiValueNumberFilter(
  2803. method='filter_by_consoleport'
  2804. )
  2805. consoleserverport_id = MultiValueNumberFilter(
  2806. method='filter_by_consoleserverport'
  2807. )
  2808. powerport_id = MultiValueNumberFilter(
  2809. method='filter_by_powerport'
  2810. )
  2811. poweroutlet_id = MultiValueNumberFilter(
  2812. method='filter_by_poweroutlet'
  2813. )
  2814. interface_id = MultiValueNumberFilter(
  2815. method='filter_by_interface'
  2816. )
  2817. frontport_id = MultiValueNumberFilter(
  2818. method='filter_by_frontport'
  2819. )
  2820. rearport_id = MultiValueNumberFilter(
  2821. method='filter_by_rearport'
  2822. )
  2823. powerfeed_id = MultiValueNumberFilter(
  2824. method='filter_by_powerfeed'
  2825. )
  2826. circuittermination_id = MultiValueNumberFilter(
  2827. method='filter_by_circuittermination'
  2828. )
  2829. class Meta:
  2830. model = CableTermination
  2831. fields = ('id', 'cable', 'cable_end', 'termination_type', 'termination_id')
  2832. def filter_by_termination_object(self, queryset, model, value):
  2833. content_type = ContentType.objects.get_for_model(model)
  2834. return queryset.filter(termination_type=content_type, termination_id__in=value)
  2835. def filter_by_consoleport(self, queryset, name, value):
  2836. return self.filter_by_termination_object(queryset, ConsolePort, value)
  2837. def filter_by_consoleserverport(self, queryset, name, value):
  2838. return self.filter_by_termination_object(queryset, ConsoleServerPort, value)
  2839. def filter_by_powerport(self, queryset, name, value):
  2840. return self.filter_by_termination_object(queryset, PowerPort, value)
  2841. def filter_by_poweroutlet(self, queryset, name, value):
  2842. return self.filter_by_termination_object(queryset, PowerOutlet, value)
  2843. def filter_by_interface(self, queryset, name, value):
  2844. return self.filter_by_termination_object(queryset, Interface, value)
  2845. def filter_by_frontport(self, queryset, name, value):
  2846. return self.filter_by_termination_object(queryset, FrontPort, value)
  2847. def filter_by_rearport(self, queryset, name, value):
  2848. return self.filter_by_termination_object(queryset, RearPort, value)
  2849. def filter_by_powerfeed(self, queryset, name, value):
  2850. return self.filter_by_termination_object(queryset, PowerFeed, value)
  2851. def filter_by_circuittermination(self, queryset, name, value):
  2852. return self.filter_by_termination_object(queryset, CircuitTermination, value)
  2853. @register_filterset
  2854. class PowerPanelFilterSet(PrimaryModelFilterSet, ContactModelFilterSet):
  2855. region_id = TreeNodeMultipleChoiceFilter(
  2856. queryset=Region.objects.all(),
  2857. field_name='site__region',
  2858. lookup_expr='in',
  2859. label=_('Region (ID)'),
  2860. )
  2861. region = TreeNodeMultipleChoiceFilter(
  2862. queryset=Region.objects.all(),
  2863. field_name='site__region',
  2864. lookup_expr='in',
  2865. to_field_name='slug',
  2866. label=_('Region (slug)'),
  2867. )
  2868. site_group_id = TreeNodeMultipleChoiceFilter(
  2869. queryset=SiteGroup.objects.all(),
  2870. field_name='site__group',
  2871. lookup_expr='in',
  2872. label=_('Site group (ID)'),
  2873. )
  2874. site_group = TreeNodeMultipleChoiceFilter(
  2875. queryset=SiteGroup.objects.all(),
  2876. field_name='site__group',
  2877. lookup_expr='in',
  2878. to_field_name='slug',
  2879. label=_('Site group (slug)'),
  2880. )
  2881. site_id = django_filters.ModelMultipleChoiceFilter(
  2882. queryset=Site.objects.all(),
  2883. distinct=False,
  2884. label=_('Site (ID)'),
  2885. )
  2886. site = django_filters.ModelMultipleChoiceFilter(
  2887. field_name='site__slug',
  2888. queryset=Site.objects.all(),
  2889. distinct=False,
  2890. to_field_name='slug',
  2891. label=_('Site name (slug)'),
  2892. )
  2893. location_id = TreeNodeMultipleChoiceFilter(
  2894. queryset=Location.objects.all(),
  2895. field_name='location',
  2896. lookup_expr='in',
  2897. label=_('Location (ID)'),
  2898. )
  2899. class Meta:
  2900. model = PowerPanel
  2901. fields = ('id', 'name', 'description')
  2902. def search(self, queryset, name, value):
  2903. if not value.strip():
  2904. return queryset
  2905. qs_filter = (
  2906. Q(name__icontains=value) |
  2907. Q(description__icontains=value)
  2908. )
  2909. return queryset.filter(qs_filter)
  2910. @register_filterset
  2911. class PowerFeedFilterSet(PrimaryModelFilterSet, CabledObjectFilterSet, PathEndpointFilterSet, TenancyFilterSet):
  2912. region_id = TreeNodeMultipleChoiceFilter(
  2913. queryset=Region.objects.all(),
  2914. field_name='power_panel__site__region',
  2915. lookup_expr='in',
  2916. label=_('Region (ID)'),
  2917. )
  2918. region = TreeNodeMultipleChoiceFilter(
  2919. queryset=Region.objects.all(),
  2920. field_name='power_panel__site__region',
  2921. lookup_expr='in',
  2922. to_field_name='slug',
  2923. label=_('Region (slug)'),
  2924. )
  2925. site_group_id = TreeNodeMultipleChoiceFilter(
  2926. queryset=SiteGroup.objects.all(),
  2927. field_name='power_panel__site__group',
  2928. lookup_expr='in',
  2929. label=_('Site group (ID)'),
  2930. )
  2931. site_group = TreeNodeMultipleChoiceFilter(
  2932. queryset=SiteGroup.objects.all(),
  2933. field_name='power_panel__site__group',
  2934. lookup_expr='in',
  2935. to_field_name='slug',
  2936. label=_('Site group (slug)'),
  2937. )
  2938. site_id = django_filters.ModelMultipleChoiceFilter(
  2939. field_name='power_panel__site',
  2940. queryset=Site.objects.all(),
  2941. distinct=False,
  2942. label=_('Site (ID)'),
  2943. )
  2944. site = django_filters.ModelMultipleChoiceFilter(
  2945. field_name='power_panel__site__slug',
  2946. queryset=Site.objects.all(),
  2947. distinct=False,
  2948. to_field_name='slug',
  2949. label=_('Site name (slug)'),
  2950. )
  2951. location_id = TreeNodeMultipleChoiceFilter(
  2952. queryset=Location.objects.all(),
  2953. field_name='power_panel__location',
  2954. lookup_expr='in',
  2955. label=_('Location (ID)'),
  2956. )
  2957. location = TreeNodeMultipleChoiceFilter(
  2958. queryset=Location.objects.all(),
  2959. field_name='power_panel__location',
  2960. lookup_expr='in',
  2961. to_field_name='slug',
  2962. label=_('Location (slug)'),
  2963. )
  2964. power_panel_id = django_filters.ModelMultipleChoiceFilter(
  2965. queryset=PowerPanel.objects.all(),
  2966. distinct=False,
  2967. label=_('Power panel (ID)'),
  2968. )
  2969. rack_id = django_filters.ModelMultipleChoiceFilter(
  2970. field_name='rack',
  2971. queryset=Rack.objects.all(),
  2972. distinct=False,
  2973. label=_('Rack (ID)'),
  2974. )
  2975. status = django_filters.MultipleChoiceFilter(
  2976. choices=PowerFeedStatusChoices,
  2977. distinct=False,
  2978. null_value=None
  2979. )
  2980. class Meta:
  2981. model = PowerFeed
  2982. fields = (
  2983. 'id', 'name', 'status', 'type', 'supply', 'phase', 'voltage', 'amperage', 'max_utilization',
  2984. 'available_power', 'mark_connected', 'cable_end', 'cable_connector', 'description',
  2985. )
  2986. def search(self, queryset, name, value):
  2987. if not value.strip():
  2988. return queryset
  2989. qs_filter = (
  2990. Q(name__icontains=value) |
  2991. Q(description__icontains=value) |
  2992. Q(power_panel__name__icontains=value) |
  2993. Q(comments__icontains=value)
  2994. )
  2995. return queryset.filter(qs_filter)
  2996. @register_filterset
  2997. class CoolingSourceFilterSet(PrimaryModelFilterSet, ContactModelFilterSet):
  2998. region_id = TreeNodeMultipleChoiceFilter(
  2999. queryset=Region.objects.all(),
  3000. field_name='site__region',
  3001. lookup_expr='in',
  3002. label=_('Region (ID)'),
  3003. )
  3004. region = TreeNodeMultipleChoiceFilter(
  3005. queryset=Region.objects.all(),
  3006. field_name='site__region',
  3007. lookup_expr='in',
  3008. to_field_name='slug',
  3009. label=_('Region (slug)'),
  3010. )
  3011. site_group_id = TreeNodeMultipleChoiceFilter(
  3012. queryset=SiteGroup.objects.all(),
  3013. field_name='site__group',
  3014. lookup_expr='in',
  3015. label=_('Site group (ID)'),
  3016. )
  3017. site_group = TreeNodeMultipleChoiceFilter(
  3018. queryset=SiteGroup.objects.all(),
  3019. field_name='site__group',
  3020. lookup_expr='in',
  3021. to_field_name='slug',
  3022. label=_('Site group (slug)'),
  3023. )
  3024. site_id = django_filters.ModelMultipleChoiceFilter(
  3025. queryset=Site.objects.all(),
  3026. distinct=False,
  3027. label=_('Site (ID)'),
  3028. )
  3029. site = django_filters.ModelMultipleChoiceFilter(
  3030. field_name='site__slug',
  3031. queryset=Site.objects.all(),
  3032. distinct=False,
  3033. to_field_name='slug',
  3034. label=_('Site name (slug)'),
  3035. )
  3036. location_id = TreeNodeMultipleChoiceFilter(
  3037. queryset=Location.objects.all(),
  3038. field_name='location',
  3039. lookup_expr='in',
  3040. label=_('Location (ID)'),
  3041. )
  3042. location = TreeNodeMultipleChoiceFilter(
  3043. queryset=Location.objects.all(),
  3044. field_name='location',
  3045. lookup_expr='in',
  3046. to_field_name='slug',
  3047. label=_('Location (slug)'),
  3048. )
  3049. type = django_filters.MultipleChoiceFilter(
  3050. choices=CoolingSourceTypeChoices,
  3051. distinct=False,
  3052. null_value=None
  3053. )
  3054. status = django_filters.MultipleChoiceFilter(
  3055. choices=CoolingSourceStatusChoices,
  3056. distinct=False,
  3057. null_value=None
  3058. )
  3059. fluid_type = django_filters.MultipleChoiceFilter(
  3060. choices=FluidTypeChoices,
  3061. distinct=False,
  3062. null_value=None
  3063. )
  3064. class Meta:
  3065. model = CoolingSource
  3066. fields = (
  3067. 'id', 'name', 'cooling_capacity', 'description',
  3068. )
  3069. def search(self, queryset, name, value):
  3070. if not value.strip():
  3071. return queryset
  3072. qs_filter = (
  3073. Q(name__icontains=value) |
  3074. Q(description__icontains=value) |
  3075. Q(comments__icontains=value)
  3076. )
  3077. return queryset.filter(qs_filter)
  3078. @register_filterset
  3079. class CoolingFeedFilterSet(PrimaryModelFilterSet, TenancyFilterSet):
  3080. region_id = TreeNodeMultipleChoiceFilter(
  3081. queryset=Region.objects.all(),
  3082. field_name='cooling_source__site__region',
  3083. lookup_expr='in',
  3084. label=_('Region (ID)'),
  3085. )
  3086. region = TreeNodeMultipleChoiceFilter(
  3087. queryset=Region.objects.all(),
  3088. field_name='cooling_source__site__region',
  3089. lookup_expr='in',
  3090. to_field_name='slug',
  3091. label=_('Region (slug)'),
  3092. )
  3093. site_group_id = TreeNodeMultipleChoiceFilter(
  3094. queryset=SiteGroup.objects.all(),
  3095. field_name='cooling_source__site__group',
  3096. lookup_expr='in',
  3097. label=_('Site group (ID)'),
  3098. )
  3099. site_group = TreeNodeMultipleChoiceFilter(
  3100. queryset=SiteGroup.objects.all(),
  3101. field_name='cooling_source__site__group',
  3102. lookup_expr='in',
  3103. to_field_name='slug',
  3104. label=_('Site group (slug)'),
  3105. )
  3106. site_id = django_filters.ModelMultipleChoiceFilter(
  3107. field_name='cooling_source__site',
  3108. queryset=Site.objects.all(),
  3109. distinct=False,
  3110. label=_('Site (ID)'),
  3111. )
  3112. site = django_filters.ModelMultipleChoiceFilter(
  3113. field_name='cooling_source__site__slug',
  3114. queryset=Site.objects.all(),
  3115. distinct=False,
  3116. to_field_name='slug',
  3117. label=_('Site name (slug)'),
  3118. )
  3119. cooling_source_id = django_filters.ModelMultipleChoiceFilter(
  3120. queryset=CoolingSource.objects.all(),
  3121. distinct=False,
  3122. label=_('Cooling source (ID)'),
  3123. )
  3124. rack_id = django_filters.ModelMultipleChoiceFilter(
  3125. field_name='rack',
  3126. queryset=Rack.objects.all(),
  3127. distinct=False,
  3128. label=_('Rack (ID)'),
  3129. )
  3130. status = django_filters.MultipleChoiceFilter(
  3131. choices=CoolingFeedStatusChoices,
  3132. distinct=False,
  3133. null_value=None
  3134. )
  3135. max_flow_unit = django_filters.MultipleChoiceFilter(
  3136. choices=FlowRateUnitChoices,
  3137. distinct=False,
  3138. null_value=None
  3139. )
  3140. class Meta:
  3141. model = CoolingFeed
  3142. fields = (
  3143. 'id', 'name', 'cooling_capacity', 'max_flow', 'description',
  3144. )
  3145. def search(self, queryset, name, value):
  3146. if not value.strip():
  3147. return queryset
  3148. qs_filter = (
  3149. Q(name__icontains=value) |
  3150. Q(description__icontains=value) |
  3151. Q(cooling_source__name__icontains=value) |
  3152. Q(comments__icontains=value)
  3153. )
  3154. return queryset.filter(qs_filter)
  3155. #
  3156. # Connection filter sets
  3157. #
  3158. class ConnectionFilterSet(BaseFilterSet):
  3159. q = django_filters.CharFilter(
  3160. method='search',
  3161. label=_('Search'),
  3162. )
  3163. site_id = MultiValueNumberFilter(
  3164. method='filter_connections',
  3165. field_name='device__site_id'
  3166. )
  3167. site = MultiValueCharFilter(
  3168. method='filter_connections',
  3169. field_name='device__site__slug'
  3170. )
  3171. device_id = MultiValueNumberFilter(
  3172. method='filter_connections',
  3173. field_name='device_id'
  3174. )
  3175. device = MultiValueCharFilter(
  3176. method='filter_connections',
  3177. field_name='device__name'
  3178. )
  3179. def filter_connections(self, queryset, name, value):
  3180. if not value:
  3181. return queryset
  3182. return queryset.filter(**{f'{name}__in': value})
  3183. def search(self, queryset, name, value):
  3184. if not value.strip():
  3185. return queryset
  3186. qs_filter = (
  3187. Q(device__name__icontains=value) |
  3188. Q(cable__label__icontains=value)
  3189. )
  3190. return queryset.filter(qs_filter)
  3191. class ConsoleConnectionFilterSet(ConnectionFilterSet):
  3192. class Meta:
  3193. model = ConsolePort
  3194. fields = ('name',)
  3195. class PowerConnectionFilterSet(ConnectionFilterSet):
  3196. class Meta:
  3197. model = PowerPort
  3198. fields = ('name',)
  3199. class InterfaceConnectionFilterSet(ConnectionFilterSet):
  3200. class Meta:
  3201. model = Interface
  3202. fields = tuple()