filters.py 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344
  1. import django_filters
  2. from django.contrib.auth.models import User
  3. from extras.filters import CustomFieldFilterSet, LocalConfigContextFilterSet, CreatedUpdatedFilterSet
  4. from tenancy.filters import TenancyFilterSet
  5. from tenancy.models import Tenant
  6. from utilities.constants import COLOR_CHOICES
  7. from utilities.filters import (
  8. BaseFilterSet, MultiValueCharFilter, MultiValueMACAddressFilter, MultiValueNumberFilter,
  9. NameSlugSearchFilterSet, NumericInFilter, TagFilter, TreeNodeMultipleChoiceFilter,
  10. )
  11. from virtualization.models import Cluster
  12. from .choices import *
  13. from .constants import *
  14. from .models import (
  15. Cable, ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device, DeviceBay,
  16. DeviceBayTemplate, DeviceRole, DeviceType, FrontPort, FrontPortTemplate, Interface, InterfaceTemplate,
  17. InventoryItem, Manufacturer, Platform, PowerFeed, PowerOutlet, PowerOutletTemplate, PowerPanel, PowerPort,
  18. PowerPortTemplate, Rack, RackGroup, RackReservation, RackRole, RearPort, RearPortTemplate, Region, Site,
  19. VirtualChassis,
  20. )
  21. __all__ = (
  22. 'CableFilterSet',
  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. 'ManufacturerFilterSet',
  40. 'PlatformFilterSet',
  41. 'PowerConnectionFilterSet',
  42. 'PowerFeedFilterSet',
  43. 'PowerOutletFilterSet',
  44. 'PowerOutletTemplateFilterSet',
  45. 'PowerPanelFilterSet',
  46. 'PowerPortFilterSet',
  47. 'PowerPortTemplateFilterSet',
  48. 'RackFilterSet',
  49. 'RackGroupFilterSet',
  50. 'RackReservationFilterSet',
  51. 'RackRoleFilterSet',
  52. 'RearPortFilterSet',
  53. 'RearPortTemplateFilterSet',
  54. 'RegionFilterSet',
  55. 'SiteFilterSet',
  56. 'VirtualChassisFilterSet',
  57. )
  58. class RegionFilterSet(BaseFilterSet, NameSlugSearchFilterSet):
  59. parent_id = django_filters.ModelMultipleChoiceFilter(
  60. queryset=Region.objects.all(),
  61. label='Parent region (ID)',
  62. )
  63. parent = django_filters.ModelMultipleChoiceFilter(
  64. field_name='parent__slug',
  65. queryset=Region.objects.all(),
  66. to_field_name='slug',
  67. label='Parent region (slug)',
  68. )
  69. class Meta:
  70. model = Region
  71. fields = ['id', 'name', 'slug']
  72. class SiteFilterSet(BaseFilterSet, TenancyFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet):
  73. id__in = NumericInFilter(
  74. field_name='id',
  75. lookup_expr='in'
  76. )
  77. q = django_filters.CharFilter(
  78. method='search',
  79. label='Search',
  80. )
  81. status = django_filters.MultipleChoiceFilter(
  82. choices=SiteStatusChoices,
  83. null_value=None
  84. )
  85. region_id = TreeNodeMultipleChoiceFilter(
  86. queryset=Region.objects.all(),
  87. field_name='region',
  88. lookup_expr='in',
  89. label='Region (ID)',
  90. )
  91. region = TreeNodeMultipleChoiceFilter(
  92. queryset=Region.objects.all(),
  93. field_name='region',
  94. lookup_expr='in',
  95. to_field_name='slug',
  96. label='Region (slug)',
  97. )
  98. tag = TagFilter()
  99. class Meta:
  100. model = Site
  101. fields = [
  102. 'id', 'name', 'slug', 'facility', 'asn', 'latitude', 'longitude', 'contact_name', 'contact_phone',
  103. 'contact_email',
  104. ]
  105. def search(self, queryset, name, value):
  106. if not value.strip():
  107. return queryset
  108. qs_filter = (
  109. Q(name__icontains=value) |
  110. Q(facility__icontains=value) |
  111. Q(description__icontains=value) |
  112. Q(physical_address__icontains=value) |
  113. Q(shipping_address__icontains=value) |
  114. Q(contact_name__icontains=value) |
  115. Q(contact_phone__icontains=value) |
  116. Q(contact_email__icontains=value) |
  117. Q(comments__icontains=value)
  118. )
  119. try:
  120. qs_filter |= Q(asn=int(value.strip()))
  121. except ValueError:
  122. pass
  123. return queryset.filter(qs_filter)
  124. class RackGroupFilterSet(BaseFilterSet, NameSlugSearchFilterSet):
  125. region_id = TreeNodeMultipleChoiceFilter(
  126. queryset=Region.objects.all(),
  127. field_name='site__region',
  128. lookup_expr='in',
  129. label='Region (ID)',
  130. )
  131. region = TreeNodeMultipleChoiceFilter(
  132. queryset=Region.objects.all(),
  133. field_name='site__region',
  134. lookup_expr='in',
  135. to_field_name='slug',
  136. label='Region (slug)',
  137. )
  138. site_id = django_filters.ModelMultipleChoiceFilter(
  139. queryset=Site.objects.all(),
  140. label='Site (ID)',
  141. )
  142. site = django_filters.ModelMultipleChoiceFilter(
  143. field_name='site__slug',
  144. queryset=Site.objects.all(),
  145. to_field_name='slug',
  146. label='Site (slug)',
  147. )
  148. class Meta:
  149. model = RackGroup
  150. fields = ['id', 'name', 'slug']
  151. class RackRoleFilterSet(BaseFilterSet, NameSlugSearchFilterSet):
  152. class Meta:
  153. model = RackRole
  154. fields = ['id', 'name', 'slug', 'color']
  155. class RackFilterSet(BaseFilterSet, TenancyFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet):
  156. id__in = NumericInFilter(
  157. field_name='id',
  158. lookup_expr='in'
  159. )
  160. q = django_filters.CharFilter(
  161. method='search',
  162. label='Search',
  163. )
  164. region_id = TreeNodeMultipleChoiceFilter(
  165. queryset=Region.objects.all(),
  166. field_name='site__region',
  167. lookup_expr='in',
  168. label='Region (ID)',
  169. )
  170. region = TreeNodeMultipleChoiceFilter(
  171. queryset=Region.objects.all(),
  172. field_name='site__region',
  173. lookup_expr='in',
  174. to_field_name='slug',
  175. label='Region (slug)',
  176. )
  177. site_id = django_filters.ModelMultipleChoiceFilter(
  178. queryset=Site.objects.all(),
  179. label='Site (ID)',
  180. )
  181. site = django_filters.ModelMultipleChoiceFilter(
  182. field_name='site__slug',
  183. queryset=Site.objects.all(),
  184. to_field_name='slug',
  185. label='Site (slug)',
  186. )
  187. group_id = django_filters.ModelMultipleChoiceFilter(
  188. queryset=RackGroup.objects.all(),
  189. label='Group (ID)',
  190. )
  191. group = django_filters.ModelMultipleChoiceFilter(
  192. field_name='group__slug',
  193. queryset=RackGroup.objects.all(),
  194. to_field_name='slug',
  195. label='Group',
  196. )
  197. status = django_filters.MultipleChoiceFilter(
  198. choices=RackStatusChoices,
  199. null_value=None
  200. )
  201. role_id = django_filters.ModelMultipleChoiceFilter(
  202. queryset=RackRole.objects.all(),
  203. label='Role (ID)',
  204. )
  205. role = django_filters.ModelMultipleChoiceFilter(
  206. field_name='role__slug',
  207. queryset=RackRole.objects.all(),
  208. to_field_name='slug',
  209. label='Role (slug)',
  210. )
  211. serial = django_filters.CharFilter(
  212. lookup_expr='iexact'
  213. )
  214. tag = TagFilter()
  215. class Meta:
  216. model = Rack
  217. fields = [
  218. 'id', 'name', 'facility_id', 'asset_tag', 'type', 'width', 'u_height', 'desc_units',
  219. 'outer_width', 'outer_depth', 'outer_unit',
  220. ]
  221. def search(self, queryset, name, value):
  222. if not value.strip():
  223. return queryset
  224. return queryset.filter(
  225. Q(name__icontains=value) |
  226. Q(facility_id__icontains=value) |
  227. Q(serial__icontains=value.strip()) |
  228. Q(asset_tag__icontains=value.strip()) |
  229. Q(comments__icontains=value)
  230. )
  231. class RackReservationFilterSet(BaseFilterSet, TenancyFilterSet):
  232. id__in = NumericInFilter(
  233. field_name='id',
  234. lookup_expr='in'
  235. )
  236. q = django_filters.CharFilter(
  237. method='search',
  238. label='Search',
  239. )
  240. rack_id = django_filters.ModelMultipleChoiceFilter(
  241. queryset=Rack.objects.all(),
  242. label='Rack (ID)',
  243. )
  244. site_id = django_filters.ModelMultipleChoiceFilter(
  245. field_name='rack__site',
  246. queryset=Site.objects.all(),
  247. label='Site (ID)',
  248. )
  249. site = django_filters.ModelMultipleChoiceFilter(
  250. field_name='rack__site__slug',
  251. queryset=Site.objects.all(),
  252. to_field_name='slug',
  253. label='Site (slug)',
  254. )
  255. group_id = django_filters.ModelMultipleChoiceFilter(
  256. field_name='rack__group',
  257. queryset=RackGroup.objects.all(),
  258. label='Group (ID)',
  259. )
  260. group = django_filters.ModelMultipleChoiceFilter(
  261. field_name='rack__group__slug',
  262. queryset=RackGroup.objects.all(),
  263. to_field_name='slug',
  264. label='Group',
  265. )
  266. user_id = django_filters.ModelMultipleChoiceFilter(
  267. queryset=User.objects.all(),
  268. label='User (ID)',
  269. )
  270. user = django_filters.ModelMultipleChoiceFilter(
  271. field_name='user',
  272. queryset=User.objects.all(),
  273. to_field_name='username',
  274. label='User (name)',
  275. )
  276. class Meta:
  277. model = RackReservation
  278. fields = ['created']
  279. def search(self, queryset, name, value):
  280. if not value.strip():
  281. return queryset
  282. return queryset.filter(
  283. Q(rack__name__icontains=value) |
  284. Q(rack__facility_id__icontains=value) |
  285. Q(user__username__icontains=value) |
  286. Q(description__icontains=value)
  287. )
  288. class ManufacturerFilterSet(BaseFilterSet, NameSlugSearchFilterSet):
  289. class Meta:
  290. model = Manufacturer
  291. fields = ['id', 'name', 'slug']
  292. class DeviceTypeFilterSet(BaseFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet):
  293. id__in = NumericInFilter(
  294. field_name='id',
  295. lookup_expr='in'
  296. )
  297. q = django_filters.CharFilter(
  298. method='search',
  299. label='Search',
  300. )
  301. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  302. queryset=Manufacturer.objects.all(),
  303. label='Manufacturer (ID)',
  304. )
  305. manufacturer = django_filters.ModelMultipleChoiceFilter(
  306. field_name='manufacturer__slug',
  307. queryset=Manufacturer.objects.all(),
  308. to_field_name='slug',
  309. label='Manufacturer (slug)',
  310. )
  311. console_ports = django_filters.BooleanFilter(
  312. method='_console_ports',
  313. label='Has console ports',
  314. )
  315. console_server_ports = django_filters.BooleanFilter(
  316. method='_console_server_ports',
  317. label='Has console server ports',
  318. )
  319. power_ports = django_filters.BooleanFilter(
  320. method='_power_ports',
  321. label='Has power ports',
  322. )
  323. power_outlets = django_filters.BooleanFilter(
  324. method='_power_outlets',
  325. label='Has power outlets',
  326. )
  327. interfaces = django_filters.BooleanFilter(
  328. method='_interfaces',
  329. label='Has interfaces',
  330. )
  331. pass_through_ports = django_filters.BooleanFilter(
  332. method='_pass_through_ports',
  333. label='Has pass-through ports',
  334. )
  335. device_bays = django_filters.BooleanFilter(
  336. method='_device_bays',
  337. label='Has device bays',
  338. )
  339. tag = TagFilter()
  340. class Meta:
  341. model = DeviceType
  342. fields = [
  343. 'model', 'slug', 'part_number', 'u_height', 'is_full_depth', 'subdevice_role',
  344. ]
  345. def search(self, queryset, name, value):
  346. if not value.strip():
  347. return queryset
  348. return queryset.filter(
  349. Q(manufacturer__name__icontains=value) |
  350. Q(model__icontains=value) |
  351. Q(part_number__icontains=value) |
  352. Q(comments__icontains=value)
  353. )
  354. def _console_ports(self, queryset, name, value):
  355. return queryset.exclude(consoleport_templates__isnull=value)
  356. def _console_server_ports(self, queryset, name, value):
  357. return queryset.exclude(consoleserverport_templates__isnull=value)
  358. def _power_ports(self, queryset, name, value):
  359. return queryset.exclude(powerport_templates__isnull=value)
  360. def _power_outlets(self, queryset, name, value):
  361. return queryset.exclude(poweroutlet_templates__isnull=value)
  362. def _interfaces(self, queryset, name, value):
  363. return queryset.exclude(interface_templates__isnull=value)
  364. def _pass_through_ports(self, queryset, name, value):
  365. return queryset.exclude(
  366. frontport_templates__isnull=value,
  367. rearport_templates__isnull=value
  368. )
  369. def _device_bays(self, queryset, name, value):
  370. return queryset.exclude(device_bay_templates__isnull=value)
  371. class DeviceTypeComponentFilterSet(NameSlugSearchFilterSet):
  372. devicetype_id = django_filters.ModelMultipleChoiceFilter(
  373. queryset=DeviceType.objects.all(),
  374. field_name='device_type_id',
  375. label='Device type (ID)',
  376. )
  377. class ConsolePortTemplateFilterSet(BaseFilterSet, DeviceTypeComponentFilterSet):
  378. class Meta:
  379. model = ConsolePortTemplate
  380. fields = ['id', 'name', 'type']
  381. class ConsoleServerPortTemplateFilterSet(BaseFilterSet, DeviceTypeComponentFilterSet):
  382. class Meta:
  383. model = ConsoleServerPortTemplate
  384. fields = ['id', 'name', 'type']
  385. class PowerPortTemplateFilterSet(BaseFilterSet, DeviceTypeComponentFilterSet):
  386. class Meta:
  387. model = PowerPortTemplate
  388. fields = ['id', 'name', 'type', 'maximum_draw', 'allocated_draw']
  389. class PowerOutletTemplateFilterSet(BaseFilterSet, DeviceTypeComponentFilterSet):
  390. class Meta:
  391. model = PowerOutletTemplate
  392. fields = ['id', 'name', 'type', 'feed_leg']
  393. class InterfaceTemplateFilterSet(BaseFilterSet, DeviceTypeComponentFilterSet):
  394. class Meta:
  395. model = InterfaceTemplate
  396. fields = ['id', 'name', 'type', 'mgmt_only']
  397. class FrontPortTemplateFilterSet(BaseFilterSet, DeviceTypeComponentFilterSet):
  398. class Meta:
  399. model = FrontPortTemplate
  400. fields = ['id', 'name', 'type']
  401. class RearPortTemplateFilterSet(BaseFilterSet, DeviceTypeComponentFilterSet):
  402. class Meta:
  403. model = RearPortTemplate
  404. fields = ['id', 'name', 'type', 'positions']
  405. class DeviceBayTemplateFilterSet(BaseFilterSet, DeviceTypeComponentFilterSet):
  406. class Meta:
  407. model = DeviceBayTemplate
  408. fields = ['id', 'name']
  409. class DeviceRoleFilterSet(BaseFilterSet, NameSlugSearchFilterSet):
  410. class Meta:
  411. model = DeviceRole
  412. fields = ['id', 'name', 'slug', 'color', 'vm_role']
  413. class PlatformFilterSet(BaseFilterSet, NameSlugSearchFilterSet):
  414. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  415. field_name='manufacturer',
  416. queryset=Manufacturer.objects.all(),
  417. label='Manufacturer (ID)',
  418. )
  419. manufacturer = django_filters.ModelMultipleChoiceFilter(
  420. field_name='manufacturer__slug',
  421. queryset=Manufacturer.objects.all(),
  422. to_field_name='slug',
  423. label='Manufacturer (slug)',
  424. )
  425. class Meta:
  426. model = Platform
  427. fields = ['id', 'name', 'slug', 'napalm_driver']
  428. class DeviceFilterSet(
  429. BaseFilterSet,
  430. TenancyFilterSet,
  431. LocalConfigContextFilterSet,
  432. CustomFieldFilterSet,
  433. CreatedUpdatedFilterSet
  434. ):
  435. id__in = NumericInFilter(
  436. field_name='id',
  437. lookup_expr='in'
  438. )
  439. q = django_filters.CharFilter(
  440. method='search',
  441. label='Search',
  442. )
  443. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  444. field_name='device_type__manufacturer',
  445. queryset=Manufacturer.objects.all(),
  446. label='Manufacturer (ID)',
  447. )
  448. manufacturer = django_filters.ModelMultipleChoiceFilter(
  449. field_name='device_type__manufacturer__slug',
  450. queryset=Manufacturer.objects.all(),
  451. to_field_name='slug',
  452. label='Manufacturer (slug)',
  453. )
  454. device_type_id = django_filters.ModelMultipleChoiceFilter(
  455. queryset=DeviceType.objects.all(),
  456. label='Device type (ID)',
  457. )
  458. role_id = django_filters.ModelMultipleChoiceFilter(
  459. field_name='device_role_id',
  460. queryset=DeviceRole.objects.all(),
  461. label='Role (ID)',
  462. )
  463. role = django_filters.ModelMultipleChoiceFilter(
  464. field_name='device_role__slug',
  465. queryset=DeviceRole.objects.all(),
  466. to_field_name='slug',
  467. label='Role (slug)',
  468. )
  469. platform_id = django_filters.ModelMultipleChoiceFilter(
  470. queryset=Platform.objects.all(),
  471. label='Platform (ID)',
  472. )
  473. platform = django_filters.ModelMultipleChoiceFilter(
  474. field_name='platform__slug',
  475. queryset=Platform.objects.all(),
  476. to_field_name='slug',
  477. label='Platform (slug)',
  478. )
  479. region_id = TreeNodeMultipleChoiceFilter(
  480. queryset=Region.objects.all(),
  481. field_name='site__region',
  482. lookup_expr='in',
  483. label='Region (ID)',
  484. )
  485. region = TreeNodeMultipleChoiceFilter(
  486. queryset=Region.objects.all(),
  487. field_name='site__region',
  488. lookup_expr='in',
  489. to_field_name='slug',
  490. label='Region (slug)',
  491. )
  492. site_id = django_filters.ModelMultipleChoiceFilter(
  493. queryset=Site.objects.all(),
  494. label='Site (ID)',
  495. )
  496. site = django_filters.ModelMultipleChoiceFilter(
  497. field_name='site__slug',
  498. queryset=Site.objects.all(),
  499. to_field_name='slug',
  500. label='Site name (slug)',
  501. )
  502. rack_group_id = django_filters.ModelMultipleChoiceFilter(
  503. field_name='rack__group',
  504. queryset=RackGroup.objects.all(),
  505. label='Rack group (ID)',
  506. )
  507. rack_id = django_filters.ModelMultipleChoiceFilter(
  508. field_name='rack',
  509. queryset=Rack.objects.all(),
  510. label='Rack (ID)',
  511. )
  512. cluster_id = django_filters.ModelMultipleChoiceFilter(
  513. queryset=Cluster.objects.all(),
  514. label='VM cluster (ID)',
  515. )
  516. model = django_filters.ModelMultipleChoiceFilter(
  517. field_name='device_type__slug',
  518. queryset=DeviceType.objects.all(),
  519. to_field_name='slug',
  520. label='Device model (slug)',
  521. )
  522. status = django_filters.MultipleChoiceFilter(
  523. choices=DeviceStatusChoices,
  524. null_value=None
  525. )
  526. is_full_depth = django_filters.BooleanFilter(
  527. field_name='device_type__is_full_depth',
  528. label='Is full depth',
  529. )
  530. mac_address = MultiValueMACAddressFilter(
  531. field_name='interfaces__mac_address',
  532. label='MAC address',
  533. )
  534. serial = django_filters.CharFilter(
  535. lookup_expr='iexact'
  536. )
  537. has_primary_ip = django_filters.BooleanFilter(
  538. method='_has_primary_ip',
  539. label='Has a primary IP',
  540. )
  541. virtual_chassis_id = django_filters.ModelMultipleChoiceFilter(
  542. field_name='virtual_chassis',
  543. queryset=VirtualChassis.objects.all(),
  544. label='Virtual chassis (ID)',
  545. )
  546. virtual_chassis_member = django_filters.BooleanFilter(
  547. method='_virtual_chassis_member',
  548. label='Is a virtual chassis member'
  549. )
  550. console_ports = django_filters.BooleanFilter(
  551. method='_console_ports',
  552. label='Has console ports',
  553. )
  554. console_server_ports = django_filters.BooleanFilter(
  555. method='_console_server_ports',
  556. label='Has console server ports',
  557. )
  558. power_ports = django_filters.BooleanFilter(
  559. method='_power_ports',
  560. label='Has power ports',
  561. )
  562. power_outlets = django_filters.BooleanFilter(
  563. method='_power_outlets',
  564. label='Has power outlets',
  565. )
  566. interfaces = django_filters.BooleanFilter(
  567. method='_interfaces',
  568. label='Has interfaces',
  569. )
  570. pass_through_ports = django_filters.BooleanFilter(
  571. method='_pass_through_ports',
  572. label='Has pass-through ports',
  573. )
  574. device_bays = django_filters.BooleanFilter(
  575. method='_device_bays',
  576. label='Has device bays',
  577. )
  578. tag = TagFilter()
  579. class Meta:
  580. model = Device
  581. fields = ['id', 'name', 'asset_tag', 'face', 'position', 'vc_position', 'vc_priority']
  582. def search(self, queryset, name, value):
  583. if not value.strip():
  584. return queryset
  585. return queryset.filter(
  586. Q(name__icontains=value) |
  587. Q(serial__icontains=value.strip()) |
  588. Q(inventory_items__serial__icontains=value.strip()) |
  589. Q(asset_tag__icontains=value.strip()) |
  590. Q(comments__icontains=value)
  591. ).distinct()
  592. def _has_primary_ip(self, queryset, name, value):
  593. if value:
  594. return queryset.filter(
  595. Q(primary_ip4__isnull=False) |
  596. Q(primary_ip6__isnull=False)
  597. )
  598. else:
  599. return queryset.exclude(
  600. Q(primary_ip4__isnull=False) |
  601. Q(primary_ip6__isnull=False)
  602. )
  603. def _virtual_chassis_member(self, queryset, name, value):
  604. return queryset.exclude(virtual_chassis__isnull=value)
  605. def _console_ports(self, queryset, name, value):
  606. return queryset.exclude(consoleports__isnull=value)
  607. def _console_server_ports(self, queryset, name, value):
  608. return queryset.exclude(consoleserverports__isnull=value)
  609. def _power_ports(self, queryset, name, value):
  610. return queryset.exclude(powerports__isnull=value)
  611. def _power_outlets(self, queryset, name, value):
  612. return queryset.exclude(poweroutlets__isnull=value)
  613. def _interfaces(self, queryset, name, value):
  614. return queryset.exclude(interfaces__isnull=value)
  615. def _pass_through_ports(self, queryset, name, value):
  616. return queryset.exclude(
  617. frontports__isnull=value,
  618. rearports__isnull=value
  619. )
  620. def _device_bays(self, queryset, name, value):
  621. return queryset.exclude(device_bays__isnull=value)
  622. class DeviceComponentFilterSet(django_filters.FilterSet):
  623. q = django_filters.CharFilter(
  624. method='search',
  625. label='Search',
  626. )
  627. region_id = TreeNodeMultipleChoiceFilter(
  628. queryset=Region.objects.all(),
  629. field_name='device__site__region',
  630. lookup_expr='in',
  631. label='Region (ID)',
  632. )
  633. region = TreeNodeMultipleChoiceFilter(
  634. queryset=Region.objects.all(),
  635. field_name='device__site__region',
  636. lookup_expr='in',
  637. to_field_name='slug',
  638. label='Region (slug)',
  639. )
  640. site_id = django_filters.ModelMultipleChoiceFilter(
  641. field_name='device__site',
  642. queryset=Site.objects.all(),
  643. label='Site (ID)',
  644. )
  645. site = django_filters.ModelMultipleChoiceFilter(
  646. field_name='device__site__slug',
  647. queryset=Site.objects.all(),
  648. to_field_name='slug',
  649. label='Site name (slug)',
  650. )
  651. device_id = django_filters.ModelMultipleChoiceFilter(
  652. queryset=Device.objects.all(),
  653. label='Device (ID)',
  654. )
  655. device = django_filters.ModelMultipleChoiceFilter(
  656. field_name='device__name',
  657. queryset=Device.objects.all(),
  658. to_field_name='name',
  659. label='Device (name)',
  660. )
  661. tag = TagFilter()
  662. def search(self, queryset, name, value):
  663. if not value.strip():
  664. return queryset
  665. return queryset.filter(
  666. Q(name__icontains=value) |
  667. Q(description__icontains=value)
  668. )
  669. class ConsolePortFilterSet(BaseFilterSet, DeviceComponentFilterSet):
  670. type = django_filters.MultipleChoiceFilter(
  671. choices=ConsolePortTypeChoices,
  672. null_value=None
  673. )
  674. cabled = django_filters.BooleanFilter(
  675. field_name='cable',
  676. lookup_expr='isnull',
  677. exclude=True
  678. )
  679. class Meta:
  680. model = ConsolePort
  681. fields = ['id', 'name', 'description', 'connection_status']
  682. class ConsoleServerPortFilterSet(BaseFilterSet, DeviceComponentFilterSet):
  683. type = django_filters.MultipleChoiceFilter(
  684. choices=ConsolePortTypeChoices,
  685. null_value=None
  686. )
  687. cabled = django_filters.BooleanFilter(
  688. field_name='cable',
  689. lookup_expr='isnull',
  690. exclude=True
  691. )
  692. class Meta:
  693. model = ConsoleServerPort
  694. fields = ['id', 'name', 'description', 'connection_status']
  695. class PowerPortFilterSet(BaseFilterSet, DeviceComponentFilterSet):
  696. type = django_filters.MultipleChoiceFilter(
  697. choices=PowerPortTypeChoices,
  698. null_value=None
  699. )
  700. cabled = django_filters.BooleanFilter(
  701. field_name='cable',
  702. lookup_expr='isnull',
  703. exclude=True
  704. )
  705. class Meta:
  706. model = PowerPort
  707. fields = ['id', 'name', 'maximum_draw', 'allocated_draw', 'description', 'connection_status']
  708. class PowerOutletFilterSet(BaseFilterSet, DeviceComponentFilterSet):
  709. type = django_filters.MultipleChoiceFilter(
  710. choices=PowerOutletTypeChoices,
  711. null_value=None
  712. )
  713. cabled = django_filters.BooleanFilter(
  714. field_name='cable',
  715. lookup_expr='isnull',
  716. exclude=True
  717. )
  718. class Meta:
  719. model = PowerOutlet
  720. fields = ['id', 'name', 'feed_leg', 'description', 'connection_status']
  721. class InterfaceFilterSet(BaseFilterSet, DeviceComponentFilterSet):
  722. q = django_filters.CharFilter(
  723. method='search',
  724. label='Search',
  725. )
  726. # Override device and device_id filters from DeviceComponentFilterSet to match against any peer virtual chassis
  727. # members
  728. device = MultiValueCharFilter(
  729. method='filter_device',
  730. field_name='name',
  731. label='Device',
  732. )
  733. device_id = MultiValueNumberFilter(
  734. method='filter_device_id',
  735. field_name='pk',
  736. label='Device (ID)',
  737. )
  738. cabled = django_filters.BooleanFilter(
  739. field_name='cable',
  740. lookup_expr='isnull',
  741. exclude=True
  742. )
  743. kind = django_filters.CharFilter(
  744. method='filter_kind',
  745. label='Kind of interface',
  746. )
  747. lag_id = django_filters.ModelMultipleChoiceFilter(
  748. field_name='lag',
  749. queryset=Interface.objects.all(),
  750. label='LAG interface (ID)',
  751. )
  752. mac_address = MultiValueMACAddressFilter()
  753. tag = TagFilter()
  754. vlan_id = django_filters.CharFilter(
  755. method='filter_vlan_id',
  756. label='Assigned VLAN'
  757. )
  758. vlan = django_filters.CharFilter(
  759. method='filter_vlan',
  760. label='Assigned VID'
  761. )
  762. type = django_filters.MultipleChoiceFilter(
  763. choices=InterfaceTypeChoices,
  764. null_value=None
  765. )
  766. class Meta:
  767. model = Interface
  768. fields = ['id', 'name', 'connection_status', 'type', 'enabled', 'mtu', 'mgmt_only', 'mode', 'description']
  769. def filter_device(self, queryset, name, value):
  770. try:
  771. devices = Device.objects.filter(**{'{}__in'.format(name): value})
  772. vc_interface_ids = []
  773. for device in devices:
  774. vc_interface_ids.extend(device.vc_interfaces.values_list('id', flat=True))
  775. return queryset.filter(pk__in=vc_interface_ids)
  776. except Device.DoesNotExist:
  777. return queryset.none()
  778. def filter_device_id(self, queryset, name, id_list):
  779. # Include interfaces belonging to peer virtual chassis members
  780. vc_interface_ids = []
  781. try:
  782. devices = Device.objects.filter(pk__in=id_list)
  783. for device in devices:
  784. vc_interface_ids += device.vc_interfaces.values_list('id', flat=True)
  785. return queryset.filter(pk__in=vc_interface_ids)
  786. except Device.DoesNotExist:
  787. return queryset.none()
  788. def filter_vlan_id(self, queryset, name, value):
  789. value = value.strip()
  790. if not value:
  791. return queryset
  792. return queryset.filter(
  793. Q(untagged_vlan_id=value) |
  794. Q(tagged_vlans=value)
  795. )
  796. def filter_vlan(self, queryset, name, value):
  797. value = value.strip()
  798. if not value:
  799. return queryset
  800. return queryset.filter(
  801. Q(untagged_vlan_id__vid=value) |
  802. Q(tagged_vlans__vid=value)
  803. )
  804. def filter_kind(self, queryset, name, value):
  805. value = value.strip().lower()
  806. return {
  807. 'physical': queryset.exclude(type__in=NONCONNECTABLE_IFACE_TYPES),
  808. 'virtual': queryset.filter(type__in=VIRTUAL_IFACE_TYPES),
  809. 'wireless': queryset.filter(type__in=WIRELESS_IFACE_TYPES),
  810. }.get(value, queryset.none())
  811. class FrontPortFilterSet(BaseFilterSet, DeviceComponentFilterSet):
  812. cabled = django_filters.BooleanFilter(
  813. field_name='cable',
  814. lookup_expr='isnull',
  815. exclude=True
  816. )
  817. class Meta:
  818. model = FrontPort
  819. fields = ['id', 'name', 'type', 'description']
  820. class RearPortFilterSet(BaseFilterSet, DeviceComponentFilterSet):
  821. cabled = django_filters.BooleanFilter(
  822. field_name='cable',
  823. lookup_expr='isnull',
  824. exclude=True
  825. )
  826. class Meta:
  827. model = RearPort
  828. fields = ['id', 'name', 'type', 'positions', 'description']
  829. class DeviceBayFilterSet(BaseFilterSet, DeviceComponentFilterSet):
  830. class Meta:
  831. model = DeviceBay
  832. fields = ['id', 'name', 'description']
  833. class InventoryItemFilterSet(BaseFilterSet, DeviceComponentFilterSet):
  834. q = django_filters.CharFilter(
  835. method='search',
  836. label='Search',
  837. )
  838. region_id = TreeNodeMultipleChoiceFilter(
  839. queryset=Region.objects.all(),
  840. field_name='device__site__region',
  841. lookup_expr='in',
  842. label='Region (ID)',
  843. )
  844. region = TreeNodeMultipleChoiceFilter(
  845. queryset=Region.objects.all(),
  846. field_name='device__site__region',
  847. lookup_expr='in',
  848. to_field_name='slug',
  849. label='Region (slug)',
  850. )
  851. site_id = django_filters.ModelMultipleChoiceFilter(
  852. field_name='device__site',
  853. queryset=Site.objects.all(),
  854. label='Site (ID)',
  855. )
  856. site = django_filters.ModelMultipleChoiceFilter(
  857. field_name='device__site__slug',
  858. queryset=Site.objects.all(),
  859. to_field_name='slug',
  860. label='Site name (slug)',
  861. )
  862. device_id = django_filters.ModelChoiceFilter(
  863. queryset=Device.objects.all(),
  864. label='Device (ID)',
  865. )
  866. device = django_filters.ModelChoiceFilter(
  867. queryset=Device.objects.all(),
  868. to_field_name='name',
  869. label='Device (name)',
  870. )
  871. parent_id = django_filters.ModelMultipleChoiceFilter(
  872. queryset=InventoryItem.objects.all(),
  873. label='Parent inventory item (ID)',
  874. )
  875. manufacturer_id = django_filters.ModelMultipleChoiceFilter(
  876. queryset=Manufacturer.objects.all(),
  877. label='Manufacturer (ID)',
  878. )
  879. manufacturer = django_filters.ModelMultipleChoiceFilter(
  880. field_name='manufacturer__slug',
  881. queryset=Manufacturer.objects.all(),
  882. to_field_name='slug',
  883. label='Manufacturer (slug)',
  884. )
  885. serial = django_filters.CharFilter(
  886. lookup_expr='iexact'
  887. )
  888. class Meta:
  889. model = InventoryItem
  890. fields = ['id', 'name', 'part_id', 'asset_tag', 'discovered']
  891. def search(self, queryset, name, value):
  892. if not value.strip():
  893. return queryset
  894. qs_filter = (
  895. Q(name__icontains=value) |
  896. Q(part_id__icontains=value) |
  897. Q(serial__icontains=value) |
  898. Q(asset_tag__icontains=value) |
  899. Q(description__icontains=value)
  900. )
  901. return queryset.filter(qs_filter)
  902. class VirtualChassisFilterSet(BaseFilterSet):
  903. q = django_filters.CharFilter(
  904. method='search',
  905. label='Search',
  906. )
  907. region_id = TreeNodeMultipleChoiceFilter(
  908. queryset=Region.objects.all(),
  909. field_name='master__site__region',
  910. lookup_expr='in',
  911. label='Region (ID)',
  912. )
  913. region = TreeNodeMultipleChoiceFilter(
  914. queryset=Region.objects.all(),
  915. field_name='master__site__region',
  916. lookup_expr='in',
  917. to_field_name='slug',
  918. label='Region (slug)',
  919. )
  920. site_id = django_filters.ModelMultipleChoiceFilter(
  921. field_name='master__site',
  922. queryset=Site.objects.all(),
  923. label='Site (ID)',
  924. )
  925. site = django_filters.ModelMultipleChoiceFilter(
  926. field_name='master__site__slug',
  927. queryset=Site.objects.all(),
  928. to_field_name='slug',
  929. label='Site name (slug)',
  930. )
  931. tenant_id = django_filters.ModelMultipleChoiceFilter(
  932. field_name='master__tenant',
  933. queryset=Tenant.objects.all(),
  934. label='Tenant (ID)',
  935. )
  936. tenant = django_filters.ModelMultipleChoiceFilter(
  937. field_name='master__tenant__slug',
  938. queryset=Tenant.objects.all(),
  939. to_field_name='slug',
  940. label='Tenant (slug)',
  941. )
  942. tag = TagFilter()
  943. class Meta:
  944. model = VirtualChassis
  945. fields = ['id', 'domain']
  946. def search(self, queryset, name, value):
  947. if not value.strip():
  948. return queryset
  949. qs_filter = (
  950. Q(master__name__icontains=value) |
  951. Q(domain__icontains=value)
  952. )
  953. return queryset.filter(qs_filter)
  954. class CableFilterSet(BaseFilterSet):
  955. q = django_filters.CharFilter(
  956. method='search',
  957. label='Search',
  958. )
  959. type = django_filters.MultipleChoiceFilter(
  960. choices=CableTypeChoices
  961. )
  962. status = django_filters.MultipleChoiceFilter(
  963. choices=CableStatusChoices
  964. )
  965. color = django_filters.MultipleChoiceFilter(
  966. choices=COLOR_CHOICES
  967. )
  968. device_id = MultiValueNumberFilter(
  969. method='filter_device'
  970. )
  971. device = MultiValueCharFilter(
  972. method='filter_device',
  973. field_name='device__name'
  974. )
  975. rack_id = MultiValueNumberFilter(
  976. method='filter_device',
  977. field_name='device__rack_id'
  978. )
  979. rack = MultiValueNumberFilter(
  980. method='filter_device',
  981. field_name='device__rack__name'
  982. )
  983. site_id = MultiValueNumberFilter(
  984. method='filter_device',
  985. field_name='device__site_id'
  986. )
  987. site = MultiValueNumberFilter(
  988. method='filter_device',
  989. field_name='device__site__slug'
  990. )
  991. tenant_id = MultiValueNumberFilter(
  992. method='filter_device',
  993. field_name='device__tenant_id'
  994. )
  995. tenant = MultiValueNumberFilter(
  996. method='filter_device',
  997. field_name='device__tenant__slug'
  998. )
  999. class Meta:
  1000. model = Cable
  1001. fields = ['id', 'label', 'length', 'length_unit']
  1002. def search(self, queryset, name, value):
  1003. if not value.strip():
  1004. return queryset
  1005. return queryset.filter(label__icontains=value)
  1006. def filter_device(self, queryset, name, value):
  1007. queryset = queryset.filter(
  1008. Q(**{'_termination_a_{}__in'.format(name): value}) |
  1009. Q(**{'_termination_b_{}__in'.format(name): value})
  1010. )
  1011. return queryset
  1012. class ConsoleConnectionFilterSet(BaseFilterSet):
  1013. site = django_filters.CharFilter(
  1014. method='filter_site',
  1015. label='Site (slug)',
  1016. )
  1017. device_id = MultiValueNumberFilter(
  1018. method='filter_device'
  1019. )
  1020. device = MultiValueCharFilter(
  1021. method='filter_device',
  1022. field_name='device__name'
  1023. )
  1024. class Meta:
  1025. model = ConsolePort
  1026. fields = ['name', 'connection_status']
  1027. def filter_site(self, queryset, name, value):
  1028. if not value.strip():
  1029. return queryset
  1030. return queryset.filter(connected_endpoint__device__site__slug=value)
  1031. def filter_device(self, queryset, name, value):
  1032. if not value:
  1033. return queryset
  1034. return queryset.filter(
  1035. Q(**{'{}__in'.format(name): value}) |
  1036. Q(**{'connected_endpoint__{}__in'.format(name): value})
  1037. )
  1038. class PowerConnectionFilterSet(BaseFilterSet):
  1039. site = django_filters.CharFilter(
  1040. method='filter_site',
  1041. label='Site (slug)',
  1042. )
  1043. device_id = MultiValueNumberFilter(
  1044. method='filter_device'
  1045. )
  1046. device = MultiValueCharFilter(
  1047. method='filter_device',
  1048. field_name='device__name'
  1049. )
  1050. class Meta:
  1051. model = PowerPort
  1052. fields = ['name', 'connection_status']
  1053. def filter_site(self, queryset, name, value):
  1054. if not value.strip():
  1055. return queryset
  1056. return queryset.filter(_connected_poweroutlet__device__site__slug=value)
  1057. def filter_device(self, queryset, name, value):
  1058. if not value:
  1059. return queryset
  1060. return queryset.filter(
  1061. Q(**{'{}__in'.format(name): value}) |
  1062. Q(**{'_connected_poweroutlet__{}__in'.format(name): value})
  1063. )
  1064. class InterfaceConnectionFilterSet(BaseFilterSet):
  1065. site = django_filters.CharFilter(
  1066. method='filter_site',
  1067. label='Site (slug)',
  1068. )
  1069. device_id = MultiValueNumberFilter(
  1070. method='filter_device'
  1071. )
  1072. device = MultiValueCharFilter(
  1073. method='filter_device',
  1074. field_name='device__name'
  1075. )
  1076. class Meta:
  1077. model = Interface
  1078. fields = ['connection_status']
  1079. def filter_site(self, queryset, name, value):
  1080. if not value.strip():
  1081. return queryset
  1082. return queryset.filter(
  1083. Q(device__site__slug=value) |
  1084. Q(_connected_interface__device__site__slug=value)
  1085. )
  1086. def filter_device(self, queryset, name, value):
  1087. if not value:
  1088. return queryset
  1089. return queryset.filter(
  1090. Q(**{'{}__in'.format(name): value}) |
  1091. Q(**{'_connected_interface__{}__in'.format(name): value})
  1092. )
  1093. class PowerPanelFilterSet(BaseFilterSet):
  1094. id__in = NumericInFilter(
  1095. field_name='id',
  1096. lookup_expr='in'
  1097. )
  1098. q = django_filters.CharFilter(
  1099. method='search',
  1100. label='Search',
  1101. )
  1102. region_id = TreeNodeMultipleChoiceFilter(
  1103. queryset=Region.objects.all(),
  1104. field_name='site__region',
  1105. lookup_expr='in',
  1106. label='Region (ID)',
  1107. )
  1108. region = TreeNodeMultipleChoiceFilter(
  1109. queryset=Region.objects.all(),
  1110. field_name='site__region',
  1111. lookup_expr='in',
  1112. to_field_name='slug',
  1113. label='Region (slug)',
  1114. )
  1115. site_id = django_filters.ModelMultipleChoiceFilter(
  1116. queryset=Site.objects.all(),
  1117. label='Site (ID)',
  1118. )
  1119. site = django_filters.ModelMultipleChoiceFilter(
  1120. field_name='site__slug',
  1121. queryset=Site.objects.all(),
  1122. to_field_name='slug',
  1123. label='Site name (slug)',
  1124. )
  1125. rack_group_id = django_filters.ModelMultipleChoiceFilter(
  1126. field_name='rack_group',
  1127. queryset=RackGroup.objects.all(),
  1128. label='Rack group (ID)',
  1129. )
  1130. class Meta:
  1131. model = PowerPanel
  1132. fields = ['name']
  1133. def search(self, queryset, name, value):
  1134. if not value.strip():
  1135. return queryset
  1136. qs_filter = (
  1137. Q(name__icontains=value)
  1138. )
  1139. return queryset.filter(qs_filter)
  1140. class PowerFeedFilterSet(BaseFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet):
  1141. id__in = NumericInFilter(
  1142. field_name='id',
  1143. lookup_expr='in'
  1144. )
  1145. q = django_filters.CharFilter(
  1146. method='search',
  1147. label='Search',
  1148. )
  1149. region_id = TreeNodeMultipleChoiceFilter(
  1150. queryset=Region.objects.all(),
  1151. field_name='power_panel__site__region',
  1152. lookup_expr='in',
  1153. label='Region (ID)',
  1154. )
  1155. region = TreeNodeMultipleChoiceFilter(
  1156. queryset=Region.objects.all(),
  1157. field_name='power_panel__site__region',
  1158. lookup_expr='in',
  1159. to_field_name='slug',
  1160. label='Region (slug)',
  1161. )
  1162. site_id = django_filters.ModelMultipleChoiceFilter(
  1163. field_name='power_panel__site',
  1164. queryset=Site.objects.all(),
  1165. label='Site (ID)',
  1166. )
  1167. site = django_filters.ModelMultipleChoiceFilter(
  1168. field_name='power_panel__site__slug',
  1169. queryset=Site.objects.all(),
  1170. to_field_name='slug',
  1171. label='Site name (slug)',
  1172. )
  1173. power_panel_id = django_filters.ModelMultipleChoiceFilter(
  1174. queryset=PowerPanel.objects.all(),
  1175. label='Power panel (ID)',
  1176. )
  1177. rack_id = django_filters.ModelMultipleChoiceFilter(
  1178. field_name='rack',
  1179. queryset=Rack.objects.all(),
  1180. label='Rack (ID)',
  1181. )
  1182. tag = TagFilter()
  1183. class Meta:
  1184. model = PowerFeed
  1185. fields = ['name', 'status', 'type', 'supply', 'phase', 'voltage', 'amperage', 'max_utilization']
  1186. def search(self, queryset, name, value):
  1187. if not value.strip():
  1188. return queryset
  1189. qs_filter = (
  1190. Q(name__icontains=value) |
  1191. Q(comments__icontains=value)
  1192. )
  1193. return queryset.filter(qs_filter)