filtersets.py 89 KB

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