filtersets.py 53 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737
  1. import django_filters
  2. from django.contrib.auth.models import User
  3. from extras.filtersets import LocalConfigContextFilterSet
  4. from ipam.models import ASN, VRF
  5. from netbox.filtersets import (
  6. BaseFilterSet, ChangeLoggedModelFilterSet, OrganizationalModelFilterSet, NetBoxModelFilterSet,
  7. )
  8. from tenancy.filtersets import TenancyFilterSet, ContactModelFilterSet
  9. from tenancy.models import *
  10. from utilities.choices import ColorChoices
  11. from utilities.filters import (
  12. ContentTypeFilter, MultiValueCharFilter, MultiValueMACAddressFilter, MultiValueNumberFilter, MultiValueWWNFilter,
  13. TreeNodeMultipleChoiceFilter,
  14. )
  15. from virtualization.models import Cluster
  16. from wireless.choices import WirelessRoleChoices, WirelessChannelChoices
  17. from .choices import *
  18. from .constants import *
  19. from .models import *
  20. __all__ = (
  21. 'CableFilterSet',
  22. 'CableTerminationFilterSet',
  23. 'ConsoleConnectionFilterSet',
  24. 'ConsolePortFilterSet',
  25. 'ConsolePortTemplateFilterSet',
  26. 'ConsoleServerPortFilterSet',
  27. 'ConsoleServerPortTemplateFilterSet',
  28. 'DeviceBayFilterSet',
  29. 'DeviceBayTemplateFilterSet',
  30. 'DeviceFilterSet',
  31. 'DeviceRoleFilterSet',
  32. 'DeviceTypeFilterSet',
  33. 'FrontPortFilterSet',
  34. 'FrontPortTemplateFilterSet',
  35. 'InterfaceConnectionFilterSet',
  36. 'InterfaceFilterSet',
  37. 'InterfaceTemplateFilterSet',
  38. 'InventoryItemFilterSet',
  39. 'InventoryItemRoleFilterSet',
  40. 'InventoryItemTemplateFilterSet',
  41. 'LocationFilterSet',
  42. 'ManufacturerFilterSet',
  43. 'ModuleBayFilterSet',
  44. 'ModuleBayTemplateFilterSet',
  45. 'ModuleFilterSet',
  46. 'ModuleTypeFilterSet',
  47. 'PathEndpointFilterSet',
  48. 'PlatformFilterSet',
  49. 'PowerConnectionFilterSet',
  50. 'PowerFeedFilterSet',
  51. 'PowerOutletFilterSet',
  52. 'PowerOutletTemplateFilterSet',
  53. 'PowerPanelFilterSet',
  54. 'PowerPortFilterSet',
  55. 'PowerPortTemplateFilterSet',
  56. 'RackFilterSet',
  57. 'RackReservationFilterSet',
  58. 'RackRoleFilterSet',
  59. 'RearPortFilterSet',
  60. 'RearPortTemplateFilterSet',
  61. 'RegionFilterSet',
  62. 'SiteFilterSet',
  63. 'SiteGroupFilterSet',
  64. 'VirtualChassisFilterSet',
  65. )
  66. class RegionFilterSet(OrganizationalModelFilterSet, ContactModelFilterSet):
  67. parent_id = django_filters.ModelMultipleChoiceFilter(
  68. queryset=Region.objects.all(),
  69. label='Parent region (ID)',
  70. )
  71. parent = django_filters.ModelMultipleChoiceFilter(
  72. field_name='parent__slug',
  73. queryset=Region.objects.all(),
  74. to_field_name='slug',
  75. label='Parent region (slug)',
  76. )
  77. class Meta:
  78. model = Region
  79. fields = ['id', 'name', 'slug', 'description']
  80. class SiteGroupFilterSet(OrganizationalModelFilterSet, ContactModelFilterSet):
  81. parent_id = django_filters.ModelMultipleChoiceFilter(
  82. queryset=SiteGroup.objects.all(),
  83. label='Parent site group (ID)',
  84. )
  85. parent = django_filters.ModelMultipleChoiceFilter(
  86. field_name='parent__slug',
  87. queryset=SiteGroup.objects.all(),
  88. to_field_name='slug',
  89. label='Parent site group (slug)',
  90. )
  91. class Meta:
  92. model = SiteGroup
  93. fields = ['id', 'name', 'slug', 'description']
  94. class SiteFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilterSet):
  95. status = django_filters.MultipleChoiceFilter(
  96. choices=SiteStatusChoices,
  97. null_value=None
  98. )
  99. region_id = TreeNodeMultipleChoiceFilter(
  100. queryset=Region.objects.all(),
  101. field_name='region',
  102. lookup_expr='in',
  103. label='Region (ID)',
  104. )
  105. region = TreeNodeMultipleChoiceFilter(
  106. queryset=Region.objects.all(),
  107. lookup_expr='in',
  108. to_field_name='slug',
  109. label='Region (slug)',
  110. )
  111. group_id = TreeNodeMultipleChoiceFilter(
  112. queryset=SiteGroup.objects.all(),
  113. field_name='group',
  114. lookup_expr='in',
  115. label='Group (ID)',
  116. )
  117. group = TreeNodeMultipleChoiceFilter(
  118. queryset=SiteGroup.objects.all(),
  119. lookup_expr='in',
  120. to_field_name='slug',
  121. label='Group (slug)',
  122. )
  123. asn = django_filters.ModelMultipleChoiceFilter(
  124. field_name='asns__asn',
  125. queryset=ASN.objects.all(),
  126. to_field_name='asn',
  127. label='AS (ID)',
  128. )
  129. asn_id = django_filters.ModelMultipleChoiceFilter(
  130. field_name='asns',
  131. queryset=ASN.objects.all(),
  132. label='AS (ID)',
  133. )
  134. class Meta:
  135. model = Site
  136. fields = (
  137. 'id', 'name', 'slug', 'facility', 'latitude', 'longitude', 'description'
  138. )
  139. def search(self, queryset, name, value):
  140. if not value.strip():
  141. return queryset
  142. qs_filter = (
  143. Q(name__icontains=value) |
  144. Q(facility__icontains=value) |
  145. Q(description__icontains=value) |
  146. Q(physical_address__icontains=value) |
  147. Q(shipping_address__icontains=value) |
  148. Q(comments__icontains=value)
  149. )
  150. try:
  151. qs_filter |= Q(asns__asn=int(value.strip()))
  152. except ValueError:
  153. pass
  154. return queryset.filter(qs_filter)
  155. class LocationFilterSet(TenancyFilterSet, ContactModelFilterSet, OrganizationalModelFilterSet):
  156. region_id = TreeNodeMultipleChoiceFilter(
  157. queryset=Region.objects.all(),
  158. field_name='site__region',
  159. lookup_expr='in',
  160. label='Region (ID)',
  161. )
  162. region = TreeNodeMultipleChoiceFilter(
  163. queryset=Region.objects.all(),
  164. field_name='site__region',
  165. lookup_expr='in',
  166. to_field_name='slug',
  167. label='Region (slug)',
  168. )
  169. site_group_id = TreeNodeMultipleChoiceFilter(
  170. queryset=SiteGroup.objects.all(),
  171. field_name='site__group',
  172. lookup_expr='in',
  173. label='Site group (ID)',
  174. )
  175. site_group = TreeNodeMultipleChoiceFilter(
  176. queryset=SiteGroup.objects.all(),
  177. field_name='site__group',
  178. lookup_expr='in',
  179. to_field_name='slug',
  180. label='Site group (slug)',
  181. )
  182. site_id = django_filters.ModelMultipleChoiceFilter(
  183. queryset=Site.objects.all(),
  184. label='Site (ID)',
  185. )
  186. site = django_filters.ModelMultipleChoiceFilter(
  187. field_name='site__slug',
  188. queryset=Site.objects.all(),
  189. to_field_name='slug',
  190. label='Site (slug)',
  191. )
  192. parent_id = TreeNodeMultipleChoiceFilter(
  193. queryset=Location.objects.all(),
  194. field_name='parent',
  195. lookup_expr='in',
  196. label='Location (ID)',
  197. )
  198. parent = TreeNodeMultipleChoiceFilter(
  199. queryset=Location.objects.all(),
  200. field_name='parent',
  201. lookup_expr='in',
  202. to_field_name='slug',
  203. label='Location (slug)',
  204. )
  205. class Meta:
  206. model = Location
  207. fields = ['id', 'name', 'slug', 'description']
  208. def search(self, queryset, name, value):
  209. if not value.strip():
  210. return queryset
  211. return queryset.filter(
  212. Q(name__icontains=value) |
  213. Q(description__icontains=value)
  214. )
  215. class RackRoleFilterSet(OrganizationalModelFilterSet):
  216. class Meta:
  217. model = RackRole
  218. fields = ['id', 'name', 'slug', 'color', 'description']
  219. class RackFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilterSet):
  220. region_id = TreeNodeMultipleChoiceFilter(
  221. queryset=Region.objects.all(),
  222. field_name='site__region',
  223. lookup_expr='in',
  224. label='Region (ID)',
  225. )
  226. region = TreeNodeMultipleChoiceFilter(
  227. queryset=Region.objects.all(),
  228. field_name='site__region',
  229. lookup_expr='in',
  230. to_field_name='slug',
  231. label='Region (slug)',
  232. )
  233. site_group_id = TreeNodeMultipleChoiceFilter(
  234. queryset=SiteGroup.objects.all(),
  235. field_name='site__group',
  236. lookup_expr='in',
  237. label='Site group (ID)',
  238. )
  239. site_group = TreeNodeMultipleChoiceFilter(
  240. queryset=SiteGroup.objects.all(),
  241. field_name='site__group',
  242. lookup_expr='in',
  243. to_field_name='slug',
  244. label='Site group (slug)',
  245. )
  246. site_id = django_filters.ModelMultipleChoiceFilter(
  247. queryset=Site.objects.all(),
  248. label='Site (ID)',
  249. )
  250. site = django_filters.ModelMultipleChoiceFilter(
  251. field_name='site__slug',
  252. queryset=Site.objects.all(),
  253. to_field_name='slug',
  254. label='Site (slug)',
  255. )
  256. location_id = TreeNodeMultipleChoiceFilter(
  257. queryset=Location.objects.all(),
  258. field_name='location',
  259. lookup_expr='in',
  260. label='Location (ID)',
  261. )
  262. location = TreeNodeMultipleChoiceFilter(
  263. queryset=Location.objects.all(),
  264. field_name='location',
  265. lookup_expr='in',
  266. to_field_name='slug',
  267. label='Location (slug)',
  268. )
  269. status = django_filters.MultipleChoiceFilter(
  270. choices=RackStatusChoices,
  271. null_value=None
  272. )
  273. type = django_filters.MultipleChoiceFilter(
  274. choices=RackTypeChoices
  275. )
  276. width = django_filters.MultipleChoiceFilter(
  277. choices=RackWidthChoices
  278. )
  279. role_id = django_filters.ModelMultipleChoiceFilter(
  280. queryset=RackRole.objects.all(),
  281. label='Role (ID)',
  282. )
  283. role = django_filters.ModelMultipleChoiceFilter(
  284. field_name='role__slug',
  285. queryset=RackRole.objects.all(),
  286. to_field_name='slug',
  287. label='Role (slug)',
  288. )
  289. serial = django_filters.CharFilter(
  290. lookup_expr='iexact'
  291. )
  292. class Meta:
  293. model = Rack
  294. fields = [
  295. 'id', 'name', 'facility_id', 'asset_tag', 'u_height', 'desc_units', 'outer_width', 'outer_depth',
  296. 'outer_unit',
  297. ]
  298. def search(self, queryset, name, value):
  299. if not value.strip():
  300. return queryset
  301. return queryset.filter(
  302. Q(name__icontains=value) |
  303. Q(facility_id__icontains=value) |
  304. Q(serial__icontains=value.strip()) |
  305. Q(asset_tag__icontains=value.strip()) |
  306. Q(comments__icontains=value)
  307. )
  308. class RackReservationFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
  309. rack_id = django_filters.ModelMultipleChoiceFilter(
  310. queryset=Rack.objects.all(),
  311. label='Rack (ID)',
  312. )
  313. site_id = django_filters.ModelMultipleChoiceFilter(
  314. field_name='rack__site',
  315. queryset=Site.objects.all(),
  316. label='Site (ID)',
  317. )
  318. site = django_filters.ModelMultipleChoiceFilter(
  319. field_name='rack__site__slug',
  320. queryset=Site.objects.all(),
  321. to_field_name='slug',
  322. label='Site (slug)',
  323. )
  324. region_id = TreeNodeMultipleChoiceFilter(
  325. queryset=Region.objects.all(),
  326. field_name='rack__site__region',
  327. lookup_expr='in',
  328. label='Region (ID)',
  329. )
  330. region = TreeNodeMultipleChoiceFilter(
  331. queryset=Region.objects.all(),
  332. field_name='rack__site__region',
  333. lookup_expr='in',
  334. to_field_name='slug',
  335. label='Region (slug)',
  336. )
  337. site_group_id = TreeNodeMultipleChoiceFilter(
  338. queryset=SiteGroup.objects.all(),
  339. field_name='rack__site__group',
  340. lookup_expr='in',
  341. label='Site group (ID)',
  342. )
  343. site_group = TreeNodeMultipleChoiceFilter(
  344. queryset=SiteGroup.objects.all(),
  345. field_name='rack__site__group',
  346. lookup_expr='in',
  347. to_field_name='slug',
  348. label='Site group (slug)',
  349. )
  350. location_id = TreeNodeMultipleChoiceFilter(
  351. queryset=Location.objects.all(),
  352. field_name='rack__location',
  353. lookup_expr='in',
  354. label='Location (ID)',
  355. )
  356. location = TreeNodeMultipleChoiceFilter(
  357. queryset=Location.objects.all(),
  358. field_name='rack__location',
  359. lookup_expr='in',
  360. to_field_name='slug',
  361. label='Location (slug)',
  362. )
  363. user_id = django_filters.ModelMultipleChoiceFilter(
  364. queryset=User.objects.all(),
  365. label='User (ID)',
  366. )
  367. user = django_filters.ModelMultipleChoiceFilter(
  368. field_name='user__username',
  369. queryset=User.objects.all(),
  370. to_field_name='username',
  371. label='User (name)',
  372. )
  373. class Meta:
  374. model = RackReservation
  375. fields = ['id', 'created', 'description']
  376. def search(self, queryset, name, value):
  377. if not value.strip():
  378. return queryset
  379. return queryset.filter(
  380. Q(rack__name__icontains=value) |
  381. Q(rack__facility_id__icontains=value) |
  382. Q(user__username__icontains=value) |
  383. Q(description__icontains=value)
  384. )
  385. class ManufacturerFilterSet(OrganizationalModelFilterSet, ContactModelFilterSet):
  386. class Meta:
  387. model = Manufacturer
  388. fields = ['id', 'name', 'slug', 'description']
  389. class DeviceTypeFilterSet(NetBoxModelFilterSet):
  390. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  391. queryset=Manufacturer.objects.all(),
  392. label='Manufacturer (ID)',
  393. )
  394. manufacturer = django_filters.ModelMultipleChoiceFilter(
  395. field_name='manufacturer__slug',
  396. queryset=Manufacturer.objects.all(),
  397. to_field_name='slug',
  398. label='Manufacturer (slug)',
  399. )
  400. console_ports = django_filters.BooleanFilter(
  401. method='_console_ports',
  402. label='Has console ports',
  403. )
  404. console_server_ports = django_filters.BooleanFilter(
  405. method='_console_server_ports',
  406. label='Has console server ports',
  407. )
  408. power_ports = django_filters.BooleanFilter(
  409. method='_power_ports',
  410. label='Has power ports',
  411. )
  412. power_outlets = django_filters.BooleanFilter(
  413. method='_power_outlets',
  414. label='Has power outlets',
  415. )
  416. interfaces = django_filters.BooleanFilter(
  417. method='_interfaces',
  418. label='Has interfaces',
  419. )
  420. pass_through_ports = django_filters.BooleanFilter(
  421. method='_pass_through_ports',
  422. label='Has pass-through ports',
  423. )
  424. module_bays = django_filters.BooleanFilter(
  425. method='_module_bays',
  426. label='Has module bays',
  427. )
  428. device_bays = django_filters.BooleanFilter(
  429. method='_device_bays',
  430. label='Has device bays',
  431. )
  432. inventory_items = django_filters.BooleanFilter(
  433. method='_inventory_items',
  434. label='Has inventory items',
  435. )
  436. class Meta:
  437. model = DeviceType
  438. fields = [
  439. 'id', 'model', 'slug', 'part_number', 'u_height', 'is_full_depth', 'subdevice_role', 'airflow',
  440. ]
  441. def search(self, queryset, name, value):
  442. if not value.strip():
  443. return queryset
  444. return queryset.filter(
  445. Q(manufacturer__name__icontains=value) |
  446. Q(model__icontains=value) |
  447. Q(part_number__icontains=value) |
  448. Q(comments__icontains=value)
  449. )
  450. def _console_ports(self, queryset, name, value):
  451. return queryset.exclude(consoleporttemplates__isnull=value)
  452. def _console_server_ports(self, queryset, name, value):
  453. return queryset.exclude(consoleserverporttemplates__isnull=value)
  454. def _power_ports(self, queryset, name, value):
  455. return queryset.exclude(powerporttemplates__isnull=value)
  456. def _power_outlets(self, queryset, name, value):
  457. return queryset.exclude(poweroutlettemplates__isnull=value)
  458. def _interfaces(self, queryset, name, value):
  459. return queryset.exclude(interfacetemplates__isnull=value)
  460. def _pass_through_ports(self, queryset, name, value):
  461. return queryset.exclude(
  462. frontporttemplates__isnull=value,
  463. rearporttemplates__isnull=value
  464. )
  465. def _module_bays(self, queryset, name, value):
  466. return queryset.exclude(modulebaytemplates__isnull=value)
  467. def _device_bays(self, queryset, name, value):
  468. return queryset.exclude(devicebaytemplates__isnull=value)
  469. def _inventory_items(self, queryset, name, value):
  470. return queryset.exclude(inventoryitemtemplates__isnull=value)
  471. class ModuleTypeFilterSet(NetBoxModelFilterSet):
  472. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  473. queryset=Manufacturer.objects.all(),
  474. label='Manufacturer (ID)',
  475. )
  476. manufacturer = django_filters.ModelMultipleChoiceFilter(
  477. field_name='manufacturer__slug',
  478. queryset=Manufacturer.objects.all(),
  479. to_field_name='slug',
  480. label='Manufacturer (slug)',
  481. )
  482. console_ports = django_filters.BooleanFilter(
  483. method='_console_ports',
  484. label='Has console ports',
  485. )
  486. console_server_ports = django_filters.BooleanFilter(
  487. method='_console_server_ports',
  488. label='Has console server ports',
  489. )
  490. power_ports = django_filters.BooleanFilter(
  491. method='_power_ports',
  492. label='Has power ports',
  493. )
  494. power_outlets = django_filters.BooleanFilter(
  495. method='_power_outlets',
  496. label='Has power outlets',
  497. )
  498. interfaces = django_filters.BooleanFilter(
  499. method='_interfaces',
  500. label='Has interfaces',
  501. )
  502. pass_through_ports = django_filters.BooleanFilter(
  503. method='_pass_through_ports',
  504. label='Has pass-through ports',
  505. )
  506. class Meta:
  507. model = ModuleType
  508. fields = ['id', 'model', 'part_number']
  509. def search(self, queryset, name, value):
  510. if not value.strip():
  511. return queryset
  512. return queryset.filter(
  513. Q(manufacturer__name__icontains=value) |
  514. Q(model__icontains=value) |
  515. Q(part_number__icontains=value) |
  516. Q(comments__icontains=value)
  517. )
  518. def _console_ports(self, queryset, name, value):
  519. return queryset.exclude(consoleporttemplates__isnull=value)
  520. def _console_server_ports(self, queryset, name, value):
  521. return queryset.exclude(consoleserverporttemplates__isnull=value)
  522. def _power_ports(self, queryset, name, value):
  523. return queryset.exclude(powerporttemplates__isnull=value)
  524. def _power_outlets(self, queryset, name, value):
  525. return queryset.exclude(poweroutlettemplates__isnull=value)
  526. def _interfaces(self, queryset, name, value):
  527. return queryset.exclude(interfacetemplates__isnull=value)
  528. def _pass_through_ports(self, queryset, name, value):
  529. return queryset.exclude(
  530. frontporttemplates__isnull=value,
  531. rearporttemplates__isnull=value
  532. )
  533. class DeviceTypeComponentFilterSet(django_filters.FilterSet):
  534. q = django_filters.CharFilter(
  535. method='search',
  536. label='Search',
  537. )
  538. devicetype_id = django_filters.ModelMultipleChoiceFilter(
  539. queryset=DeviceType.objects.all(),
  540. field_name='device_type_id',
  541. label='Device type (ID)',
  542. )
  543. def search(self, queryset, name, value):
  544. if not value.strip():
  545. return queryset
  546. return queryset.filter(name__icontains=value)
  547. class ModularDeviceTypeComponentFilterSet(DeviceTypeComponentFilterSet):
  548. moduletype_id = django_filters.ModelMultipleChoiceFilter(
  549. queryset=ModuleType.objects.all(),
  550. field_name='module_type_id',
  551. label='Module type (ID)',
  552. )
  553. class ConsolePortTemplateFilterSet(ChangeLoggedModelFilterSet, ModularDeviceTypeComponentFilterSet):
  554. class Meta:
  555. model = ConsolePortTemplate
  556. fields = ['id', 'name', 'type']
  557. class ConsoleServerPortTemplateFilterSet(ChangeLoggedModelFilterSet, ModularDeviceTypeComponentFilterSet):
  558. class Meta:
  559. model = ConsoleServerPortTemplate
  560. fields = ['id', 'name', 'type']
  561. class PowerPortTemplateFilterSet(ChangeLoggedModelFilterSet, ModularDeviceTypeComponentFilterSet):
  562. class Meta:
  563. model = PowerPortTemplate
  564. fields = ['id', 'name', 'type', 'maximum_draw', 'allocated_draw']
  565. class PowerOutletTemplateFilterSet(ChangeLoggedModelFilterSet, ModularDeviceTypeComponentFilterSet):
  566. feed_leg = django_filters.MultipleChoiceFilter(
  567. choices=PowerOutletFeedLegChoices,
  568. null_value=None
  569. )
  570. class Meta:
  571. model = PowerOutletTemplate
  572. fields = ['id', 'name', 'type', 'feed_leg']
  573. class InterfaceTemplateFilterSet(ChangeLoggedModelFilterSet, ModularDeviceTypeComponentFilterSet):
  574. type = django_filters.MultipleChoiceFilter(
  575. choices=InterfaceTypeChoices,
  576. null_value=None
  577. )
  578. class Meta:
  579. model = InterfaceTemplate
  580. fields = ['id', 'name', 'type', 'mgmt_only']
  581. class FrontPortTemplateFilterSet(ChangeLoggedModelFilterSet, ModularDeviceTypeComponentFilterSet):
  582. type = django_filters.MultipleChoiceFilter(
  583. choices=PortTypeChoices,
  584. null_value=None
  585. )
  586. class Meta:
  587. model = FrontPortTemplate
  588. fields = ['id', 'name', 'type', 'color']
  589. class RearPortTemplateFilterSet(ChangeLoggedModelFilterSet, ModularDeviceTypeComponentFilterSet):
  590. type = django_filters.MultipleChoiceFilter(
  591. choices=PortTypeChoices,
  592. null_value=None
  593. )
  594. class Meta:
  595. model = RearPortTemplate
  596. fields = ['id', 'name', 'type', 'color', 'positions']
  597. class ModuleBayTemplateFilterSet(ChangeLoggedModelFilterSet, DeviceTypeComponentFilterSet):
  598. class Meta:
  599. model = ModuleBayTemplate
  600. fields = ['id', 'name']
  601. class DeviceBayTemplateFilterSet(ChangeLoggedModelFilterSet, DeviceTypeComponentFilterSet):
  602. class Meta:
  603. model = DeviceBayTemplate
  604. fields = ['id', 'name']
  605. class InventoryItemTemplateFilterSet(ChangeLoggedModelFilterSet, DeviceTypeComponentFilterSet):
  606. parent_id = django_filters.ModelMultipleChoiceFilter(
  607. queryset=InventoryItemTemplate.objects.all(),
  608. label='Parent inventory item (ID)',
  609. )
  610. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  611. queryset=Manufacturer.objects.all(),
  612. label='Manufacturer (ID)',
  613. )
  614. manufacturer = django_filters.ModelMultipleChoiceFilter(
  615. field_name='manufacturer__slug',
  616. queryset=Manufacturer.objects.all(),
  617. to_field_name='slug',
  618. label='Manufacturer (slug)',
  619. )
  620. role_id = django_filters.ModelMultipleChoiceFilter(
  621. queryset=InventoryItemRole.objects.all(),
  622. label='Role (ID)',
  623. )
  624. role = django_filters.ModelMultipleChoiceFilter(
  625. field_name='role__slug',
  626. queryset=InventoryItemRole.objects.all(),
  627. to_field_name='slug',
  628. label='Role (slug)',
  629. )
  630. component_type = ContentTypeFilter()
  631. component_id = MultiValueNumberFilter()
  632. class Meta:
  633. model = InventoryItemTemplate
  634. fields = ['id', 'name', 'label', 'part_id']
  635. def search(self, queryset, name, value):
  636. if not value.strip():
  637. return queryset
  638. qs_filter = (
  639. Q(name__icontains=value) |
  640. Q(part_id__icontains=value) |
  641. Q(description__icontains=value)
  642. )
  643. return queryset.filter(qs_filter)
  644. class DeviceRoleFilterSet(OrganizationalModelFilterSet):
  645. class Meta:
  646. model = DeviceRole
  647. fields = ['id', 'name', 'slug', 'color', 'vm_role', 'description']
  648. class PlatformFilterSet(OrganizationalModelFilterSet):
  649. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  650. field_name='manufacturer',
  651. queryset=Manufacturer.objects.all(),
  652. label='Manufacturer (ID)',
  653. )
  654. manufacturer = django_filters.ModelMultipleChoiceFilter(
  655. field_name='manufacturer__slug',
  656. queryset=Manufacturer.objects.all(),
  657. to_field_name='slug',
  658. label='Manufacturer (slug)',
  659. )
  660. class Meta:
  661. model = Platform
  662. fields = ['id', 'name', 'slug', 'napalm_driver', 'description']
  663. class DeviceFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilterSet, LocalConfigContextFilterSet):
  664. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  665. field_name='device_type__manufacturer',
  666. queryset=Manufacturer.objects.all(),
  667. label='Manufacturer (ID)',
  668. )
  669. manufacturer = django_filters.ModelMultipleChoiceFilter(
  670. field_name='device_type__manufacturer__slug',
  671. queryset=Manufacturer.objects.all(),
  672. to_field_name='slug',
  673. label='Manufacturer (slug)',
  674. )
  675. device_type_id = django_filters.ModelMultipleChoiceFilter(
  676. queryset=DeviceType.objects.all(),
  677. label='Device type (ID)',
  678. )
  679. role_id = django_filters.ModelMultipleChoiceFilter(
  680. field_name='device_role_id',
  681. queryset=DeviceRole.objects.all(),
  682. label='Role (ID)',
  683. )
  684. role = django_filters.ModelMultipleChoiceFilter(
  685. field_name='device_role__slug',
  686. queryset=DeviceRole.objects.all(),
  687. to_field_name='slug',
  688. label='Role (slug)',
  689. )
  690. parent_device_id = django_filters.ModelMultipleChoiceFilter(
  691. field_name='parent_bay__device',
  692. queryset=Device.objects.all(),
  693. label='Parent Device (ID)',
  694. )
  695. platform_id = django_filters.ModelMultipleChoiceFilter(
  696. queryset=Platform.objects.all(),
  697. label='Platform (ID)',
  698. )
  699. platform = django_filters.ModelMultipleChoiceFilter(
  700. field_name='platform__slug',
  701. queryset=Platform.objects.all(),
  702. to_field_name='slug',
  703. label='Platform (slug)',
  704. )
  705. region_id = TreeNodeMultipleChoiceFilter(
  706. queryset=Region.objects.all(),
  707. field_name='site__region',
  708. lookup_expr='in',
  709. label='Region (ID)',
  710. )
  711. region = TreeNodeMultipleChoiceFilter(
  712. queryset=Region.objects.all(),
  713. field_name='site__region',
  714. lookup_expr='in',
  715. to_field_name='slug',
  716. label='Region (slug)',
  717. )
  718. site_group_id = TreeNodeMultipleChoiceFilter(
  719. queryset=SiteGroup.objects.all(),
  720. field_name='site__group',
  721. lookup_expr='in',
  722. label='Site group (ID)',
  723. )
  724. site_group = TreeNodeMultipleChoiceFilter(
  725. queryset=SiteGroup.objects.all(),
  726. field_name='site__group',
  727. lookup_expr='in',
  728. to_field_name='slug',
  729. label='Site group (slug)',
  730. )
  731. site_id = django_filters.ModelMultipleChoiceFilter(
  732. queryset=Site.objects.all(),
  733. label='Site (ID)',
  734. )
  735. site = django_filters.ModelMultipleChoiceFilter(
  736. field_name='site__slug',
  737. queryset=Site.objects.all(),
  738. to_field_name='slug',
  739. label='Site name (slug)',
  740. )
  741. location_id = TreeNodeMultipleChoiceFilter(
  742. queryset=Location.objects.all(),
  743. field_name='location',
  744. lookup_expr='in',
  745. label='Location (ID)',
  746. )
  747. rack_id = django_filters.ModelMultipleChoiceFilter(
  748. field_name='rack',
  749. queryset=Rack.objects.all(),
  750. label='Rack (ID)',
  751. )
  752. cluster_id = django_filters.ModelMultipleChoiceFilter(
  753. queryset=Cluster.objects.all(),
  754. label='VM cluster (ID)',
  755. )
  756. model = django_filters.ModelMultipleChoiceFilter(
  757. field_name='device_type__slug',
  758. queryset=DeviceType.objects.all(),
  759. to_field_name='slug',
  760. label='Device model (slug)',
  761. )
  762. status = django_filters.MultipleChoiceFilter(
  763. choices=DeviceStatusChoices,
  764. null_value=None
  765. )
  766. is_full_depth = django_filters.BooleanFilter(
  767. field_name='device_type__is_full_depth',
  768. label='Is full depth',
  769. )
  770. mac_address = MultiValueMACAddressFilter(
  771. field_name='interfaces__mac_address',
  772. label='MAC address',
  773. )
  774. serial = MultiValueCharFilter(
  775. lookup_expr='iexact'
  776. )
  777. has_primary_ip = django_filters.BooleanFilter(
  778. method='_has_primary_ip',
  779. label='Has a primary IP',
  780. )
  781. virtual_chassis_id = django_filters.ModelMultipleChoiceFilter(
  782. field_name='virtual_chassis',
  783. queryset=VirtualChassis.objects.all(),
  784. label='Virtual chassis (ID)',
  785. )
  786. virtual_chassis_member = django_filters.BooleanFilter(
  787. method='_virtual_chassis_member',
  788. label='Is a virtual chassis member'
  789. )
  790. console_ports = django_filters.BooleanFilter(
  791. method='_console_ports',
  792. label='Has console ports',
  793. )
  794. console_server_ports = django_filters.BooleanFilter(
  795. method='_console_server_ports',
  796. label='Has console server ports',
  797. )
  798. power_ports = django_filters.BooleanFilter(
  799. method='_power_ports',
  800. label='Has power ports',
  801. )
  802. power_outlets = django_filters.BooleanFilter(
  803. method='_power_outlets',
  804. label='Has power outlets',
  805. )
  806. interfaces = django_filters.BooleanFilter(
  807. method='_interfaces',
  808. label='Has interfaces',
  809. )
  810. pass_through_ports = django_filters.BooleanFilter(
  811. method='_pass_through_ports',
  812. label='Has pass-through ports',
  813. )
  814. module_bays = django_filters.BooleanFilter(
  815. method='_module_bays',
  816. label='Has module bays',
  817. )
  818. device_bays = django_filters.BooleanFilter(
  819. method='_device_bays',
  820. label='Has device bays',
  821. )
  822. class Meta:
  823. model = Device
  824. fields = ['id', 'name', 'asset_tag', 'face', 'position', 'airflow', 'vc_position', 'vc_priority']
  825. def search(self, queryset, name, value):
  826. if not value.strip():
  827. return queryset
  828. return queryset.filter(
  829. Q(name__icontains=value) |
  830. Q(serial__icontains=value.strip()) |
  831. Q(inventoryitems__serial__icontains=value.strip()) |
  832. Q(asset_tag__icontains=value.strip()) |
  833. Q(comments__icontains=value)
  834. ).distinct()
  835. def _has_primary_ip(self, queryset, name, value):
  836. params = Q(primary_ip4__isnull=False) | Q(primary_ip6__isnull=False)
  837. if value:
  838. return queryset.filter(params)
  839. return queryset.exclude(params)
  840. def _virtual_chassis_member(self, queryset, name, value):
  841. return queryset.exclude(virtual_chassis__isnull=value)
  842. def _console_ports(self, queryset, name, value):
  843. return queryset.exclude(consoleports__isnull=value)
  844. def _console_server_ports(self, queryset, name, value):
  845. return queryset.exclude(consoleserverports__isnull=value)
  846. def _power_ports(self, queryset, name, value):
  847. return queryset.exclude(powerports__isnull=value)
  848. def _power_outlets(self, queryset, name, value):
  849. return queryset.exclude(poweroutlets__isnull=value)
  850. def _interfaces(self, queryset, name, value):
  851. return queryset.exclude(interfaces__isnull=value)
  852. def _pass_through_ports(self, queryset, name, value):
  853. return queryset.exclude(
  854. frontports__isnull=value,
  855. rearports__isnull=value
  856. )
  857. def _module_bays(self, queryset, name, value):
  858. return queryset.exclude(modulebays__isnull=value)
  859. def _device_bays(self, queryset, name, value):
  860. return queryset.exclude(devicebays__isnull=value)
  861. class ModuleFilterSet(NetBoxModelFilterSet):
  862. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  863. field_name='module_type__manufacturer',
  864. queryset=Manufacturer.objects.all(),
  865. label='Manufacturer (ID)',
  866. )
  867. manufacturer = django_filters.ModelMultipleChoiceFilter(
  868. field_name='module_type__manufacturer__slug',
  869. queryset=Manufacturer.objects.all(),
  870. to_field_name='slug',
  871. label='Manufacturer (slug)',
  872. )
  873. module_type_id = django_filters.ModelMultipleChoiceFilter(
  874. field_name='module_type',
  875. queryset=ModuleType.objects.all(),
  876. label='Module type (ID)',
  877. )
  878. module_type = django_filters.ModelMultipleChoiceFilter(
  879. field_name='module_type__model',
  880. queryset=ModuleType.objects.all(),
  881. to_field_name='model',
  882. label='Module type (model)',
  883. )
  884. device_id = django_filters.ModelMultipleChoiceFilter(
  885. queryset=Device.objects.all(),
  886. label='Device (ID)',
  887. )
  888. class Meta:
  889. model = Module
  890. fields = ['id', 'serial', 'asset_tag']
  891. def search(self, queryset, name, value):
  892. if not value.strip():
  893. return queryset
  894. return queryset.filter(
  895. Q(serial__icontains=value.strip()) |
  896. Q(asset_tag__icontains=value.strip()) |
  897. Q(comments__icontains=value)
  898. ).distinct()
  899. class DeviceComponentFilterSet(django_filters.FilterSet):
  900. q = django_filters.CharFilter(
  901. method='search',
  902. label='Search',
  903. )
  904. region_id = TreeNodeMultipleChoiceFilter(
  905. queryset=Region.objects.all(),
  906. field_name='device__site__region',
  907. lookup_expr='in',
  908. label='Region (ID)',
  909. )
  910. region = TreeNodeMultipleChoiceFilter(
  911. queryset=Region.objects.all(),
  912. field_name='device__site__region',
  913. lookup_expr='in',
  914. to_field_name='slug',
  915. label='Region (slug)',
  916. )
  917. site_group_id = TreeNodeMultipleChoiceFilter(
  918. queryset=SiteGroup.objects.all(),
  919. field_name='device__site__group',
  920. lookup_expr='in',
  921. label='Site group (ID)',
  922. )
  923. site_group = TreeNodeMultipleChoiceFilter(
  924. queryset=SiteGroup.objects.all(),
  925. field_name='device__site__group',
  926. lookup_expr='in',
  927. to_field_name='slug',
  928. label='Site group (slug)',
  929. )
  930. site_id = django_filters.ModelMultipleChoiceFilter(
  931. field_name='device__site',
  932. queryset=Site.objects.all(),
  933. label='Site (ID)',
  934. )
  935. site = django_filters.ModelMultipleChoiceFilter(
  936. field_name='device__site__slug',
  937. queryset=Site.objects.all(),
  938. to_field_name='slug',
  939. label='Site name (slug)',
  940. )
  941. location_id = django_filters.ModelMultipleChoiceFilter(
  942. field_name='device__location',
  943. queryset=Location.objects.all(),
  944. label='Location (ID)',
  945. )
  946. location = django_filters.ModelMultipleChoiceFilter(
  947. field_name='device__location__slug',
  948. queryset=Location.objects.all(),
  949. to_field_name='slug',
  950. label='Location (slug)',
  951. )
  952. device_id = django_filters.ModelMultipleChoiceFilter(
  953. queryset=Device.objects.all(),
  954. label='Device (ID)',
  955. )
  956. device = django_filters.ModelMultipleChoiceFilter(
  957. field_name='device__name',
  958. queryset=Device.objects.all(),
  959. to_field_name='name',
  960. label='Device (name)',
  961. )
  962. virtual_chassis_id = django_filters.ModelMultipleChoiceFilter(
  963. field_name='device__virtual_chassis',
  964. queryset=VirtualChassis.objects.all(),
  965. label='Virtual Chassis (ID)'
  966. )
  967. virtual_chassis = django_filters.ModelMultipleChoiceFilter(
  968. field_name='device__virtual_chassis__name',
  969. queryset=VirtualChassis.objects.all(),
  970. to_field_name='name',
  971. label='Virtual Chassis',
  972. )
  973. def search(self, queryset, name, value):
  974. if not value.strip():
  975. return queryset
  976. return queryset.filter(
  977. Q(name__icontains=value) |
  978. Q(label__icontains=value) |
  979. Q(description__icontains=value)
  980. )
  981. class ModularDeviceComponentFilterSet(DeviceComponentFilterSet):
  982. """
  983. Extends DeviceComponentFilterSet to add a module_id filter for components
  984. which can be associated with a particular module within a device.
  985. """
  986. module_id = django_filters.ModelMultipleChoiceFilter(
  987. queryset=Module.objects.all(),
  988. label='Module (ID)',
  989. )
  990. class CableTerminationFilterSet(django_filters.FilterSet):
  991. cabled = django_filters.BooleanFilter(
  992. field_name='cable',
  993. lookup_expr='isnull',
  994. exclude=True
  995. )
  996. class PathEndpointFilterSet(django_filters.FilterSet):
  997. connected = django_filters.BooleanFilter(
  998. method='filter_connected'
  999. )
  1000. def filter_connected(self, queryset, name, value):
  1001. if value:
  1002. return queryset.filter(_path__is_active=True)
  1003. else:
  1004. return queryset.filter(Q(_path__isnull=True) | Q(_path__is_active=False))
  1005. class ConsolePortFilterSet(
  1006. ModularDeviceComponentFilterSet,
  1007. NetBoxModelFilterSet,
  1008. CableTerminationFilterSet,
  1009. PathEndpointFilterSet
  1010. ):
  1011. type = django_filters.MultipleChoiceFilter(
  1012. choices=ConsolePortTypeChoices,
  1013. null_value=None
  1014. )
  1015. class Meta:
  1016. model = ConsolePort
  1017. fields = ['id', 'name', 'label', 'description']
  1018. class ConsoleServerPortFilterSet(
  1019. ModularDeviceComponentFilterSet,
  1020. NetBoxModelFilterSet,
  1021. CableTerminationFilterSet,
  1022. PathEndpointFilterSet
  1023. ):
  1024. type = django_filters.MultipleChoiceFilter(
  1025. choices=ConsolePortTypeChoices,
  1026. null_value=None
  1027. )
  1028. class Meta:
  1029. model = ConsoleServerPort
  1030. fields = ['id', 'name', 'label', 'description']
  1031. class PowerPortFilterSet(
  1032. ModularDeviceComponentFilterSet,
  1033. NetBoxModelFilterSet,
  1034. CableTerminationFilterSet,
  1035. PathEndpointFilterSet
  1036. ):
  1037. type = django_filters.MultipleChoiceFilter(
  1038. choices=PowerPortTypeChoices,
  1039. null_value=None
  1040. )
  1041. class Meta:
  1042. model = PowerPort
  1043. fields = ['id', 'name', 'label', 'maximum_draw', 'allocated_draw', 'description']
  1044. class PowerOutletFilterSet(
  1045. ModularDeviceComponentFilterSet,
  1046. NetBoxModelFilterSet,
  1047. CableTerminationFilterSet,
  1048. PathEndpointFilterSet
  1049. ):
  1050. type = django_filters.MultipleChoiceFilter(
  1051. choices=PowerOutletTypeChoices,
  1052. null_value=None
  1053. )
  1054. feed_leg = django_filters.MultipleChoiceFilter(
  1055. choices=PowerOutletFeedLegChoices,
  1056. null_value=None
  1057. )
  1058. class Meta:
  1059. model = PowerOutlet
  1060. fields = ['id', 'name', 'label', 'feed_leg', 'description']
  1061. class InterfaceFilterSet(
  1062. ModularDeviceComponentFilterSet,
  1063. NetBoxModelFilterSet,
  1064. CableTerminationFilterSet,
  1065. PathEndpointFilterSet
  1066. ):
  1067. # Override device and device_id filters from DeviceComponentFilterSet to match against any peer virtual chassis
  1068. # members
  1069. device = MultiValueCharFilter(
  1070. method='filter_device',
  1071. field_name='name',
  1072. label='Device',
  1073. )
  1074. device_id = MultiValueNumberFilter(
  1075. method='filter_device_id',
  1076. field_name='pk',
  1077. label='Device (ID)',
  1078. )
  1079. kind = django_filters.CharFilter(
  1080. method='filter_kind',
  1081. label='Kind of interface',
  1082. )
  1083. parent_id = django_filters.ModelMultipleChoiceFilter(
  1084. field_name='parent',
  1085. queryset=Interface.objects.all(),
  1086. label='Parent interface (ID)',
  1087. )
  1088. bridge_id = django_filters.ModelMultipleChoiceFilter(
  1089. field_name='bridge',
  1090. queryset=Interface.objects.all(),
  1091. label='Bridged interface (ID)',
  1092. )
  1093. lag_id = django_filters.ModelMultipleChoiceFilter(
  1094. field_name='lag',
  1095. queryset=Interface.objects.all(),
  1096. label='LAG interface (ID)',
  1097. )
  1098. speed = MultiValueNumberFilter()
  1099. duplex = django_filters.MultipleChoiceFilter(
  1100. choices=InterfaceDuplexChoices
  1101. )
  1102. mac_address = MultiValueMACAddressFilter()
  1103. wwn = MultiValueWWNFilter()
  1104. vlan_id = django_filters.CharFilter(
  1105. method='filter_vlan_id',
  1106. label='Assigned VLAN'
  1107. )
  1108. vlan = django_filters.CharFilter(
  1109. method='filter_vlan',
  1110. label='Assigned VID'
  1111. )
  1112. type = django_filters.MultipleChoiceFilter(
  1113. choices=InterfaceTypeChoices,
  1114. null_value=None
  1115. )
  1116. rf_role = django_filters.MultipleChoiceFilter(
  1117. choices=WirelessRoleChoices
  1118. )
  1119. rf_channel = django_filters.MultipleChoiceFilter(
  1120. choices=WirelessChannelChoices
  1121. )
  1122. vrf_id = django_filters.ModelMultipleChoiceFilter(
  1123. field_name='vrf',
  1124. queryset=VRF.objects.all(),
  1125. label='VRF',
  1126. )
  1127. vrf = django_filters.ModelMultipleChoiceFilter(
  1128. field_name='vrf__rd',
  1129. queryset=VRF.objects.all(),
  1130. to_field_name='rd',
  1131. label='VRF (RD)',
  1132. )
  1133. class Meta:
  1134. model = Interface
  1135. fields = [
  1136. 'id', 'name', 'label', 'type', 'enabled', 'mtu', 'mgmt_only', 'mode', 'rf_role', 'rf_channel',
  1137. 'rf_channel_frequency', 'rf_channel_width', 'tx_power', 'description',
  1138. ]
  1139. def filter_device(self, queryset, name, value):
  1140. try:
  1141. devices = Device.objects.filter(**{'{}__in'.format(name): value})
  1142. vc_interface_ids = []
  1143. for device in devices:
  1144. vc_interface_ids.extend(device.vc_interfaces().values_list('id', flat=True))
  1145. return queryset.filter(pk__in=vc_interface_ids)
  1146. except Device.DoesNotExist:
  1147. return queryset.none()
  1148. def filter_device_id(self, queryset, name, id_list):
  1149. # Include interfaces belonging to peer virtual chassis members
  1150. vc_interface_ids = []
  1151. try:
  1152. devices = Device.objects.filter(pk__in=id_list)
  1153. for device in devices:
  1154. vc_interface_ids += device.vc_interfaces().values_list('id', flat=True)
  1155. return queryset.filter(pk__in=vc_interface_ids)
  1156. except Device.DoesNotExist:
  1157. return queryset.none()
  1158. def filter_vlan_id(self, queryset, name, value):
  1159. value = value.strip()
  1160. if not value:
  1161. return queryset
  1162. return queryset.filter(
  1163. Q(untagged_vlan_id=value) |
  1164. Q(tagged_vlans=value)
  1165. )
  1166. def filter_vlan(self, queryset, name, value):
  1167. value = value.strip()
  1168. if not value:
  1169. return queryset
  1170. return queryset.filter(
  1171. Q(untagged_vlan_id__vid=value) |
  1172. Q(tagged_vlans__vid=value)
  1173. )
  1174. def filter_kind(self, queryset, name, value):
  1175. value = value.strip().lower()
  1176. return {
  1177. 'physical': queryset.exclude(type__in=NONCONNECTABLE_IFACE_TYPES),
  1178. 'virtual': queryset.filter(type__in=VIRTUAL_IFACE_TYPES),
  1179. 'wireless': queryset.filter(type__in=WIRELESS_IFACE_TYPES),
  1180. }.get(value, queryset.none())
  1181. class FrontPortFilterSet(
  1182. ModularDeviceComponentFilterSet,
  1183. NetBoxModelFilterSet,
  1184. CableTerminationFilterSet
  1185. ):
  1186. type = django_filters.MultipleChoiceFilter(
  1187. choices=PortTypeChoices,
  1188. null_value=None
  1189. )
  1190. class Meta:
  1191. model = FrontPort
  1192. fields = ['id', 'name', 'label', 'type', 'color', 'description']
  1193. class RearPortFilterSet(
  1194. ModularDeviceComponentFilterSet,
  1195. NetBoxModelFilterSet,
  1196. CableTerminationFilterSet
  1197. ):
  1198. type = django_filters.MultipleChoiceFilter(
  1199. choices=PortTypeChoices,
  1200. null_value=None
  1201. )
  1202. class Meta:
  1203. model = RearPort
  1204. fields = ['id', 'name', 'label', 'type', 'color', 'positions', 'description']
  1205. class ModuleBayFilterSet(DeviceComponentFilterSet, NetBoxModelFilterSet):
  1206. class Meta:
  1207. model = ModuleBay
  1208. fields = ['id', 'name', 'label', 'description']
  1209. class DeviceBayFilterSet(DeviceComponentFilterSet, NetBoxModelFilterSet):
  1210. class Meta:
  1211. model = DeviceBay
  1212. fields = ['id', 'name', 'label', 'description']
  1213. class InventoryItemFilterSet(DeviceComponentFilterSet, NetBoxModelFilterSet):
  1214. parent_id = django_filters.ModelMultipleChoiceFilter(
  1215. queryset=InventoryItem.objects.all(),
  1216. label='Parent inventory item (ID)',
  1217. )
  1218. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  1219. queryset=Manufacturer.objects.all(),
  1220. label='Manufacturer (ID)',
  1221. )
  1222. manufacturer = django_filters.ModelMultipleChoiceFilter(
  1223. field_name='manufacturer__slug',
  1224. queryset=Manufacturer.objects.all(),
  1225. to_field_name='slug',
  1226. label='Manufacturer (slug)',
  1227. )
  1228. role_id = django_filters.ModelMultipleChoiceFilter(
  1229. queryset=InventoryItemRole.objects.all(),
  1230. label='Role (ID)',
  1231. )
  1232. role = django_filters.ModelMultipleChoiceFilter(
  1233. field_name='role__slug',
  1234. queryset=InventoryItemRole.objects.all(),
  1235. to_field_name='slug',
  1236. label='Role (slug)',
  1237. )
  1238. component_type = ContentTypeFilter()
  1239. component_id = MultiValueNumberFilter()
  1240. serial = django_filters.CharFilter(
  1241. lookup_expr='iexact'
  1242. )
  1243. class Meta:
  1244. model = InventoryItem
  1245. fields = ['id', 'name', 'label', 'part_id', 'asset_tag', 'discovered']
  1246. def search(self, queryset, name, value):
  1247. if not value.strip():
  1248. return queryset
  1249. qs_filter = (
  1250. Q(name__icontains=value) |
  1251. Q(part_id__icontains=value) |
  1252. Q(serial__icontains=value) |
  1253. Q(asset_tag__icontains=value) |
  1254. Q(description__icontains=value)
  1255. )
  1256. return queryset.filter(qs_filter)
  1257. class InventoryItemRoleFilterSet(OrganizationalModelFilterSet):
  1258. class Meta:
  1259. model = InventoryItemRole
  1260. fields = ['id', 'name', 'slug', 'color']
  1261. class VirtualChassisFilterSet(NetBoxModelFilterSet):
  1262. master_id = django_filters.ModelMultipleChoiceFilter(
  1263. queryset=Device.objects.all(),
  1264. label='Master (ID)',
  1265. )
  1266. master = django_filters.ModelMultipleChoiceFilter(
  1267. field_name='master__name',
  1268. queryset=Device.objects.all(),
  1269. to_field_name='name',
  1270. label='Master (name)',
  1271. )
  1272. region_id = TreeNodeMultipleChoiceFilter(
  1273. queryset=Region.objects.all(),
  1274. field_name='master__site__region',
  1275. lookup_expr='in',
  1276. label='Region (ID)',
  1277. )
  1278. region = TreeNodeMultipleChoiceFilter(
  1279. queryset=Region.objects.all(),
  1280. field_name='master__site__region',
  1281. lookup_expr='in',
  1282. to_field_name='slug',
  1283. label='Region (slug)',
  1284. )
  1285. site_group_id = TreeNodeMultipleChoiceFilter(
  1286. queryset=SiteGroup.objects.all(),
  1287. field_name='master__site__group',
  1288. lookup_expr='in',
  1289. label='Site group (ID)',
  1290. )
  1291. site_group = TreeNodeMultipleChoiceFilter(
  1292. queryset=SiteGroup.objects.all(),
  1293. field_name='master__site__group',
  1294. lookup_expr='in',
  1295. to_field_name='slug',
  1296. label='Site group (slug)',
  1297. )
  1298. site_id = django_filters.ModelMultipleChoiceFilter(
  1299. field_name='master__site',
  1300. queryset=Site.objects.all(),
  1301. label='Site (ID)',
  1302. )
  1303. site = django_filters.ModelMultipleChoiceFilter(
  1304. field_name='master__site__slug',
  1305. queryset=Site.objects.all(),
  1306. to_field_name='slug',
  1307. label='Site name (slug)',
  1308. )
  1309. tenant_id = django_filters.ModelMultipleChoiceFilter(
  1310. field_name='master__tenant',
  1311. queryset=Tenant.objects.all(),
  1312. label='Tenant (ID)',
  1313. )
  1314. tenant = django_filters.ModelMultipleChoiceFilter(
  1315. field_name='master__tenant__slug',
  1316. queryset=Tenant.objects.all(),
  1317. to_field_name='slug',
  1318. label='Tenant (slug)',
  1319. )
  1320. class Meta:
  1321. model = VirtualChassis
  1322. fields = ['id', 'domain', 'name']
  1323. def search(self, queryset, name, value):
  1324. if not value.strip():
  1325. return queryset
  1326. qs_filter = (
  1327. Q(name__icontains=value) |
  1328. Q(members__name__icontains=value) |
  1329. Q(domain__icontains=value)
  1330. )
  1331. return queryset.filter(qs_filter).distinct()
  1332. class CableFilterSet(TenancyFilterSet, NetBoxModelFilterSet):
  1333. termination_a_type = ContentTypeFilter()
  1334. termination_a_id = MultiValueNumberFilter()
  1335. termination_b_type = ContentTypeFilter()
  1336. termination_b_id = MultiValueNumberFilter()
  1337. type = django_filters.MultipleChoiceFilter(
  1338. choices=CableTypeChoices
  1339. )
  1340. status = django_filters.MultipleChoiceFilter(
  1341. choices=LinkStatusChoices
  1342. )
  1343. color = django_filters.MultipleChoiceFilter(
  1344. choices=ColorChoices
  1345. )
  1346. device_id = MultiValueNumberFilter(
  1347. method='filter_device'
  1348. )
  1349. device = MultiValueCharFilter(
  1350. method='filter_device',
  1351. field_name='device__name'
  1352. )
  1353. rack_id = MultiValueNumberFilter(
  1354. method='filter_device',
  1355. field_name='device__rack_id'
  1356. )
  1357. rack = MultiValueCharFilter(
  1358. method='filter_device',
  1359. field_name='device__rack__name'
  1360. )
  1361. site_id = MultiValueNumberFilter(
  1362. method='filter_device',
  1363. field_name='device__site_id'
  1364. )
  1365. site = MultiValueCharFilter(
  1366. method='filter_device',
  1367. field_name='device__site__slug'
  1368. )
  1369. class Meta:
  1370. model = Cable
  1371. fields = ['id', 'label', 'length', 'length_unit', 'termination_a_id', 'termination_b_id']
  1372. def search(self, queryset, name, value):
  1373. if not value.strip():
  1374. return queryset
  1375. return queryset.filter(label__icontains=value)
  1376. def filter_device(self, queryset, name, value):
  1377. queryset = queryset.filter(
  1378. Q(**{'_termination_a_{}__in'.format(name): value}) |
  1379. Q(**{'_termination_b_{}__in'.format(name): value})
  1380. )
  1381. return queryset
  1382. class PowerPanelFilterSet(NetBoxModelFilterSet, ContactModelFilterSet):
  1383. region_id = TreeNodeMultipleChoiceFilter(
  1384. queryset=Region.objects.all(),
  1385. field_name='site__region',
  1386. lookup_expr='in',
  1387. label='Region (ID)',
  1388. )
  1389. region = TreeNodeMultipleChoiceFilter(
  1390. queryset=Region.objects.all(),
  1391. field_name='site__region',
  1392. lookup_expr='in',
  1393. to_field_name='slug',
  1394. label='Region (slug)',
  1395. )
  1396. site_group_id = TreeNodeMultipleChoiceFilter(
  1397. queryset=SiteGroup.objects.all(),
  1398. field_name='site__group',
  1399. lookup_expr='in',
  1400. label='Site group (ID)',
  1401. )
  1402. site_group = TreeNodeMultipleChoiceFilter(
  1403. queryset=SiteGroup.objects.all(),
  1404. field_name='site__group',
  1405. lookup_expr='in',
  1406. to_field_name='slug',
  1407. label='Site group (slug)',
  1408. )
  1409. site_id = django_filters.ModelMultipleChoiceFilter(
  1410. queryset=Site.objects.all(),
  1411. label='Site (ID)',
  1412. )
  1413. site = django_filters.ModelMultipleChoiceFilter(
  1414. field_name='site__slug',
  1415. queryset=Site.objects.all(),
  1416. to_field_name='slug',
  1417. label='Site name (slug)',
  1418. )
  1419. location_id = TreeNodeMultipleChoiceFilter(
  1420. queryset=Location.objects.all(),
  1421. field_name='location',
  1422. lookup_expr='in',
  1423. label='Location (ID)',
  1424. )
  1425. class Meta:
  1426. model = PowerPanel
  1427. fields = ['id', 'name']
  1428. def search(self, queryset, name, value):
  1429. if not value.strip():
  1430. return queryset
  1431. qs_filter = (
  1432. Q(name__icontains=value)
  1433. )
  1434. return queryset.filter(qs_filter)
  1435. class PowerFeedFilterSet(NetBoxModelFilterSet, CableTerminationFilterSet, PathEndpointFilterSet):
  1436. region_id = TreeNodeMultipleChoiceFilter(
  1437. queryset=Region.objects.all(),
  1438. field_name='power_panel__site__region',
  1439. lookup_expr='in',
  1440. label='Region (ID)',
  1441. )
  1442. region = TreeNodeMultipleChoiceFilter(
  1443. queryset=Region.objects.all(),
  1444. field_name='power_panel__site__region',
  1445. lookup_expr='in',
  1446. to_field_name='slug',
  1447. label='Region (slug)',
  1448. )
  1449. site_group_id = TreeNodeMultipleChoiceFilter(
  1450. queryset=SiteGroup.objects.all(),
  1451. field_name='power_panel__site__group',
  1452. lookup_expr='in',
  1453. label='Site group (ID)',
  1454. )
  1455. site_group = TreeNodeMultipleChoiceFilter(
  1456. queryset=SiteGroup.objects.all(),
  1457. field_name='power_panel__site__group',
  1458. lookup_expr='in',
  1459. to_field_name='slug',
  1460. label='Site group (slug)',
  1461. )
  1462. site_id = django_filters.ModelMultipleChoiceFilter(
  1463. field_name='power_panel__site',
  1464. queryset=Site.objects.all(),
  1465. label='Site (ID)',
  1466. )
  1467. site = django_filters.ModelMultipleChoiceFilter(
  1468. field_name='power_panel__site__slug',
  1469. queryset=Site.objects.all(),
  1470. to_field_name='slug',
  1471. label='Site name (slug)',
  1472. )
  1473. power_panel_id = django_filters.ModelMultipleChoiceFilter(
  1474. queryset=PowerPanel.objects.all(),
  1475. label='Power panel (ID)',
  1476. )
  1477. rack_id = django_filters.ModelMultipleChoiceFilter(
  1478. field_name='rack',
  1479. queryset=Rack.objects.all(),
  1480. label='Rack (ID)',
  1481. )
  1482. status = django_filters.MultipleChoiceFilter(
  1483. choices=PowerFeedStatusChoices,
  1484. null_value=None
  1485. )
  1486. class Meta:
  1487. model = PowerFeed
  1488. fields = ['id', 'name', 'status', 'type', 'supply', 'phase', 'voltage', 'amperage', 'max_utilization']
  1489. def search(self, queryset, name, value):
  1490. if not value.strip():
  1491. return queryset
  1492. qs_filter = (
  1493. Q(name__icontains=value) |
  1494. Q(comments__icontains=value)
  1495. )
  1496. return queryset.filter(qs_filter)
  1497. #
  1498. # Connection filter sets
  1499. #
  1500. class ConnectionFilterSet(BaseFilterSet):
  1501. q = django_filters.CharFilter(
  1502. method='search',
  1503. label='Search',
  1504. )
  1505. site_id = MultiValueNumberFilter(
  1506. method='filter_connections',
  1507. field_name='device__site_id'
  1508. )
  1509. site = MultiValueCharFilter(
  1510. method='filter_connections',
  1511. field_name='device__site__slug'
  1512. )
  1513. device_id = MultiValueNumberFilter(
  1514. method='filter_connections',
  1515. field_name='device_id'
  1516. )
  1517. device = MultiValueCharFilter(
  1518. method='filter_connections',
  1519. field_name='device__name'
  1520. )
  1521. def filter_connections(self, queryset, name, value):
  1522. if not value:
  1523. return queryset
  1524. return queryset.filter(**{f'{name}__in': value})
  1525. def search(self, queryset, name, value):
  1526. if not value.strip():
  1527. return queryset
  1528. qs_filter = (
  1529. Q(device__name__icontains=value) |
  1530. Q(cable__label__icontains=value)
  1531. )
  1532. return queryset.filter(qs_filter)
  1533. class ConsoleConnectionFilterSet(ConnectionFilterSet):
  1534. class Meta:
  1535. model = ConsolePort
  1536. fields = ['name']
  1537. class PowerConnectionFilterSet(ConnectionFilterSet):
  1538. class Meta:
  1539. model = PowerPort
  1540. fields = ['name']
  1541. class InterfaceConnectionFilterSet(ConnectionFilterSet):
  1542. class Meta:
  1543. model = Interface
  1544. fields = []