filtersets.py 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922
  1. import django_filters
  2. import netaddr
  3. from django.contrib.contenttypes.models import ContentType
  4. from django.core.exceptions import ValidationError
  5. from django.db.models import Q
  6. from netaddr.core import AddrFormatError
  7. from dcim.models import Device, Interface, Region, Site, SiteGroup
  8. from netbox.filtersets import ChangeLoggedModelFilterSet, OrganizationalModelFilterSet, NetBoxModelFilterSet
  9. from tenancy.filtersets import TenancyFilterSet
  10. from utilities.filters import (
  11. ContentTypeFilter, MultiValueCharFilter, MultiValueNumberFilter, NumericArrayFilter, TreeNodeMultipleChoiceFilter,
  12. )
  13. from virtualization.models import VirtualMachine, VMInterface
  14. from .choices import *
  15. from .models import *
  16. __all__ = (
  17. 'AggregateFilterSet',
  18. 'ASNFilterSet',
  19. 'FHRPGroupAssignmentFilterSet',
  20. 'FHRPGroupFilterSet',
  21. 'IPAddressFilterSet',
  22. 'IPRangeFilterSet',
  23. 'PrefixFilterSet',
  24. 'RIRFilterSet',
  25. 'RoleFilterSet',
  26. 'RouteTargetFilterSet',
  27. 'ServiceFilterSet',
  28. 'ServiceTemplateFilterSet',
  29. 'VLANFilterSet',
  30. 'VLANGroupFilterSet',
  31. 'VRFFilterSet',
  32. )
  33. class VRFFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
  34. import_target_id = django_filters.ModelMultipleChoiceFilter(
  35. field_name='import_targets',
  36. queryset=RouteTarget.objects.all(),
  37. label='Import target',
  38. )
  39. import_target = django_filters.ModelMultipleChoiceFilter(
  40. field_name='import_targets__name',
  41. queryset=RouteTarget.objects.all(),
  42. to_field_name='name',
  43. label='Import target (name)',
  44. )
  45. export_target_id = django_filters.ModelMultipleChoiceFilter(
  46. field_name='export_targets',
  47. queryset=RouteTarget.objects.all(),
  48. label='Export target',
  49. )
  50. export_target = django_filters.ModelMultipleChoiceFilter(
  51. field_name='export_targets__name',
  52. queryset=RouteTarget.objects.all(),
  53. to_field_name='name',
  54. label='Export target (name)',
  55. )
  56. def search(self, queryset, name, value):
  57. if not value.strip():
  58. return queryset
  59. return queryset.filter(
  60. Q(name__icontains=value) |
  61. Q(rd__icontains=value) |
  62. Q(description__icontains=value)
  63. )
  64. class Meta:
  65. model = VRF
  66. fields = ['id', 'name', 'rd', 'enforce_unique', 'description']
  67. class RouteTargetFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
  68. importing_vrf_id = django_filters.ModelMultipleChoiceFilter(
  69. field_name='importing_vrfs',
  70. queryset=VRF.objects.all(),
  71. label='Importing VRF',
  72. )
  73. importing_vrf = django_filters.ModelMultipleChoiceFilter(
  74. field_name='importing_vrfs__rd',
  75. queryset=VRF.objects.all(),
  76. to_field_name='rd',
  77. label='Import VRF (RD)',
  78. )
  79. exporting_vrf_id = django_filters.ModelMultipleChoiceFilter(
  80. field_name='exporting_vrfs',
  81. queryset=VRF.objects.all(),
  82. label='Exporting VRF',
  83. )
  84. exporting_vrf = django_filters.ModelMultipleChoiceFilter(
  85. field_name='exporting_vrfs__rd',
  86. queryset=VRF.objects.all(),
  87. to_field_name='rd',
  88. label='Export VRF (RD)',
  89. )
  90. def search(self, queryset, name, value):
  91. if not value.strip():
  92. return queryset
  93. return queryset.filter(
  94. Q(name__icontains=value) |
  95. Q(description__icontains=value)
  96. )
  97. class Meta:
  98. model = RouteTarget
  99. fields = ['id', 'name', 'description']
  100. class RIRFilterSet(OrganizationalModelFilterSet):
  101. class Meta:
  102. model = RIR
  103. fields = ['id', 'name', 'slug', 'is_private', 'description']
  104. class AggregateFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
  105. family = django_filters.NumberFilter(
  106. field_name='prefix',
  107. lookup_expr='family'
  108. )
  109. prefix = django_filters.CharFilter(
  110. method='filter_prefix',
  111. label='Prefix',
  112. )
  113. rir_id = django_filters.ModelMultipleChoiceFilter(
  114. queryset=RIR.objects.all(),
  115. label='RIR (ID)',
  116. )
  117. rir = django_filters.ModelMultipleChoiceFilter(
  118. field_name='rir__slug',
  119. queryset=RIR.objects.all(),
  120. to_field_name='slug',
  121. label='RIR (slug)',
  122. )
  123. class Meta:
  124. model = Aggregate
  125. fields = ['id', 'date_added', 'description']
  126. def search(self, queryset, name, value):
  127. if not value.strip():
  128. return queryset
  129. qs_filter = Q(description__icontains=value)
  130. qs_filter |= Q(prefix__contains=value.strip())
  131. try:
  132. prefix = str(netaddr.IPNetwork(value.strip()).cidr)
  133. qs_filter |= Q(prefix__net_contains_or_equals=prefix)
  134. qs_filter |= Q(prefix__contains=value.strip())
  135. except (AddrFormatError, ValueError):
  136. pass
  137. return queryset.filter(qs_filter)
  138. def filter_prefix(self, queryset, name, value):
  139. if not value.strip():
  140. return queryset
  141. try:
  142. query = str(netaddr.IPNetwork(value).cidr)
  143. return queryset.filter(prefix=query)
  144. except (AddrFormatError, ValueError):
  145. return queryset.none()
  146. class ASNFilterSet(OrganizationalModelFilterSet, TenancyFilterSet):
  147. rir_id = django_filters.ModelMultipleChoiceFilter(
  148. queryset=RIR.objects.all(),
  149. label='RIR (ID)',
  150. )
  151. rir = django_filters.ModelMultipleChoiceFilter(
  152. field_name='rir__slug',
  153. queryset=RIR.objects.all(),
  154. to_field_name='slug',
  155. label='RIR (slug)',
  156. )
  157. site_id = django_filters.ModelMultipleChoiceFilter(
  158. field_name='sites',
  159. queryset=Site.objects.all(),
  160. label='Site (ID)',
  161. )
  162. site = django_filters.ModelMultipleChoiceFilter(
  163. field_name='sites__slug',
  164. queryset=Site.objects.all(),
  165. to_field_name='slug',
  166. label='Site (slug)',
  167. )
  168. class Meta:
  169. model = ASN
  170. fields = ['id', 'asn', 'description']
  171. def search(self, queryset, name, value):
  172. if not value.strip():
  173. return queryset
  174. qs_filter = Q(description__icontains=value)
  175. try:
  176. qs_filter |= Q(asn=int(value))
  177. except ValueError:
  178. pass
  179. return queryset.filter(qs_filter)
  180. class RoleFilterSet(OrganizationalModelFilterSet):
  181. class Meta:
  182. model = Role
  183. fields = ['id', 'name', 'slug', 'description']
  184. class PrefixFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
  185. family = django_filters.NumberFilter(
  186. field_name='prefix',
  187. lookup_expr='family'
  188. )
  189. prefix = MultiValueCharFilter(
  190. method='filter_prefix',
  191. label='Prefix',
  192. )
  193. within = django_filters.CharFilter(
  194. method='search_within',
  195. label='Within prefix',
  196. )
  197. within_include = django_filters.CharFilter(
  198. method='search_within_include',
  199. label='Within and including prefix',
  200. )
  201. contains = django_filters.CharFilter(
  202. method='search_contains',
  203. label='Prefixes which contain this prefix or IP',
  204. )
  205. depth = MultiValueNumberFilter(
  206. field_name='_depth'
  207. )
  208. children = MultiValueNumberFilter(
  209. field_name='_children'
  210. )
  211. mask_length = MultiValueNumberFilter(
  212. field_name='prefix',
  213. lookup_expr='net_mask_length'
  214. )
  215. mask_length__gte = django_filters.NumberFilter(
  216. field_name='prefix',
  217. lookup_expr='net_mask_length__gte'
  218. )
  219. mask_length__lte = django_filters.NumberFilter(
  220. field_name='prefix',
  221. lookup_expr='net_mask_length__lte'
  222. )
  223. vrf_id = django_filters.ModelMultipleChoiceFilter(
  224. queryset=VRF.objects.all(),
  225. label='VRF',
  226. )
  227. vrf = django_filters.ModelMultipleChoiceFilter(
  228. field_name='vrf__rd',
  229. queryset=VRF.objects.all(),
  230. to_field_name='rd',
  231. label='VRF (RD)',
  232. )
  233. present_in_vrf_id = django_filters.ModelChoiceFilter(
  234. queryset=VRF.objects.all(),
  235. method='filter_present_in_vrf',
  236. label='VRF'
  237. )
  238. present_in_vrf = django_filters.ModelChoiceFilter(
  239. queryset=VRF.objects.all(),
  240. method='filter_present_in_vrf',
  241. to_field_name='rd',
  242. label='VRF (RD)',
  243. )
  244. region_id = TreeNodeMultipleChoiceFilter(
  245. queryset=Region.objects.all(),
  246. field_name='site__region',
  247. lookup_expr='in',
  248. label='Region (ID)',
  249. )
  250. region = TreeNodeMultipleChoiceFilter(
  251. queryset=Region.objects.all(),
  252. field_name='site__region',
  253. lookup_expr='in',
  254. to_field_name='slug',
  255. label='Region (slug)',
  256. )
  257. site_group_id = TreeNodeMultipleChoiceFilter(
  258. queryset=SiteGroup.objects.all(),
  259. field_name='site__group',
  260. lookup_expr='in',
  261. label='Site group (ID)',
  262. )
  263. site_group = TreeNodeMultipleChoiceFilter(
  264. queryset=SiteGroup.objects.all(),
  265. field_name='site__group',
  266. lookup_expr='in',
  267. to_field_name='slug',
  268. label='Site group (slug)',
  269. )
  270. site_id = django_filters.ModelMultipleChoiceFilter(
  271. queryset=Site.objects.all(),
  272. label='Site (ID)',
  273. )
  274. site = django_filters.ModelMultipleChoiceFilter(
  275. field_name='site__slug',
  276. queryset=Site.objects.all(),
  277. to_field_name='slug',
  278. label='Site (slug)',
  279. )
  280. vlan_id = django_filters.ModelMultipleChoiceFilter(
  281. queryset=VLAN.objects.all(),
  282. label='VLAN (ID)',
  283. )
  284. vlan_vid = django_filters.NumberFilter(
  285. field_name='vlan__vid',
  286. label='VLAN number (1-4094)',
  287. )
  288. role_id = django_filters.ModelMultipleChoiceFilter(
  289. queryset=Role.objects.all(),
  290. label='Role (ID)',
  291. )
  292. role = django_filters.ModelMultipleChoiceFilter(
  293. field_name='role__slug',
  294. queryset=Role.objects.all(),
  295. to_field_name='slug',
  296. label='Role (slug)',
  297. )
  298. status = django_filters.MultipleChoiceFilter(
  299. choices=PrefixStatusChoices,
  300. null_value=None
  301. )
  302. class Meta:
  303. model = Prefix
  304. fields = ['id', 'is_pool', 'mark_utilized', 'description']
  305. def search(self, queryset, name, value):
  306. if not value.strip():
  307. return queryset
  308. qs_filter = Q(description__icontains=value)
  309. qs_filter |= Q(prefix__contains=value.strip())
  310. try:
  311. prefix = str(netaddr.IPNetwork(value.strip()).cidr)
  312. qs_filter |= Q(prefix__net_contains_or_equals=prefix)
  313. qs_filter |= Q(prefix__contains=value.strip())
  314. except (AddrFormatError, ValueError):
  315. pass
  316. return queryset.filter(qs_filter)
  317. def filter_prefix(self, queryset, name, value):
  318. query_values = []
  319. for v in value:
  320. try:
  321. query_values.append(netaddr.IPNetwork(v))
  322. except (AddrFormatError, ValueError):
  323. pass
  324. return queryset.filter(prefix__in=query_values)
  325. def search_within(self, queryset, name, value):
  326. value = value.strip()
  327. if not value:
  328. return queryset
  329. try:
  330. query = str(netaddr.IPNetwork(value).cidr)
  331. return queryset.filter(prefix__net_contained=query)
  332. except (AddrFormatError, ValueError):
  333. return queryset.none()
  334. def search_within_include(self, queryset, name, value):
  335. value = value.strip()
  336. if not value:
  337. return queryset
  338. try:
  339. query = str(netaddr.IPNetwork(value).cidr)
  340. return queryset.filter(prefix__net_contained_or_equal=query)
  341. except (AddrFormatError, ValueError):
  342. return queryset.none()
  343. def search_contains(self, queryset, name, value):
  344. value = value.strip()
  345. if not value:
  346. return queryset
  347. try:
  348. # Searching by prefix
  349. if '/' in value:
  350. return queryset.filter(prefix__net_contains_or_equals=str(netaddr.IPNetwork(value).cidr))
  351. # Searching by IP address
  352. else:
  353. return queryset.filter(prefix__net_contains=str(netaddr.IPAddress(value)))
  354. except (AddrFormatError, ValueError):
  355. return queryset.none()
  356. def filter_present_in_vrf(self, queryset, name, vrf):
  357. if vrf is None:
  358. return queryset.none
  359. return queryset.filter(
  360. Q(vrf=vrf) |
  361. Q(vrf__export_targets__in=vrf.import_targets.all())
  362. )
  363. class IPRangeFilterSet(TenancyFilterSet, NetBoxModelFilterSet):
  364. family = django_filters.NumberFilter(
  365. field_name='start_address',
  366. lookup_expr='family'
  367. )
  368. contains = django_filters.CharFilter(
  369. method='search_contains',
  370. label='Ranges which contain this prefix or IP',
  371. )
  372. vrf_id = django_filters.ModelMultipleChoiceFilter(
  373. queryset=VRF.objects.all(),
  374. label='VRF',
  375. )
  376. vrf = django_filters.ModelMultipleChoiceFilter(
  377. field_name='vrf__rd',
  378. queryset=VRF.objects.all(),
  379. to_field_name='rd',
  380. label='VRF (RD)',
  381. )
  382. role_id = django_filters.ModelMultipleChoiceFilter(
  383. queryset=Role.objects.all(),
  384. label='Role (ID)',
  385. )
  386. role = django_filters.ModelMultipleChoiceFilter(
  387. field_name='role__slug',
  388. queryset=Role.objects.all(),
  389. to_field_name='slug',
  390. label='Role (slug)',
  391. )
  392. status = django_filters.MultipleChoiceFilter(
  393. choices=IPRangeStatusChoices,
  394. null_value=None
  395. )
  396. class Meta:
  397. model = IPRange
  398. fields = ['id', 'description']
  399. def search(self, queryset, name, value):
  400. if not value.strip():
  401. return queryset
  402. qs_filter = Q(description__icontains=value)
  403. try:
  404. ipaddress = str(netaddr.IPNetwork(value.strip()).cidr)
  405. qs_filter |= Q(start_address=ipaddress)
  406. qs_filter |= Q(end_address=ipaddress)
  407. except (AddrFormatError, ValueError):
  408. pass
  409. return queryset.filter(qs_filter)
  410. def search_contains(self, queryset, name, value):
  411. value = value.strip()
  412. if not value:
  413. return queryset
  414. try:
  415. # Strip mask
  416. ipaddress = netaddr.IPNetwork(value)
  417. return queryset.filter(start_address__lte=ipaddress, end_address__gte=ipaddress)
  418. except (AddrFormatError, ValueError):
  419. return queryset.none()
  420. class IPAddressFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
  421. family = django_filters.NumberFilter(
  422. field_name='address',
  423. lookup_expr='family'
  424. )
  425. parent = django_filters.CharFilter(
  426. method='search_by_parent',
  427. label='Parent prefix',
  428. )
  429. address = MultiValueCharFilter(
  430. method='filter_address',
  431. label='Address',
  432. )
  433. mask_length = django_filters.NumberFilter(
  434. method='filter_mask_length',
  435. label='Mask length',
  436. )
  437. vrf_id = django_filters.ModelMultipleChoiceFilter(
  438. queryset=VRF.objects.all(),
  439. label='VRF',
  440. )
  441. vrf = django_filters.ModelMultipleChoiceFilter(
  442. field_name='vrf__rd',
  443. queryset=VRF.objects.all(),
  444. to_field_name='rd',
  445. label='VRF (RD)',
  446. )
  447. present_in_vrf_id = django_filters.ModelChoiceFilter(
  448. queryset=VRF.objects.all(),
  449. method='filter_present_in_vrf',
  450. label='VRF'
  451. )
  452. present_in_vrf = django_filters.ModelChoiceFilter(
  453. queryset=VRF.objects.all(),
  454. method='filter_present_in_vrf',
  455. to_field_name='rd',
  456. label='VRF (RD)',
  457. )
  458. device = MultiValueCharFilter(
  459. method='filter_device',
  460. field_name='name',
  461. label='Device (name)',
  462. )
  463. device_id = MultiValueNumberFilter(
  464. method='filter_device',
  465. field_name='pk',
  466. label='Device (ID)',
  467. )
  468. virtual_machine = MultiValueCharFilter(
  469. method='filter_virtual_machine',
  470. field_name='name',
  471. label='Virtual machine (name)',
  472. )
  473. virtual_machine_id = MultiValueNumberFilter(
  474. method='filter_virtual_machine',
  475. field_name='pk',
  476. label='Virtual machine (ID)',
  477. )
  478. interface = django_filters.ModelMultipleChoiceFilter(
  479. field_name='interface__name',
  480. queryset=Interface.objects.all(),
  481. to_field_name='name',
  482. label='Interface (name)',
  483. )
  484. interface_id = django_filters.ModelMultipleChoiceFilter(
  485. field_name='interface',
  486. queryset=Interface.objects.all(),
  487. label='Interface (ID)',
  488. )
  489. vminterface = django_filters.ModelMultipleChoiceFilter(
  490. field_name='vminterface__name',
  491. queryset=VMInterface.objects.all(),
  492. to_field_name='name',
  493. label='VM interface (name)',
  494. )
  495. vminterface_id = django_filters.ModelMultipleChoiceFilter(
  496. field_name='vminterface',
  497. queryset=VMInterface.objects.all(),
  498. label='VM interface (ID)',
  499. )
  500. fhrpgroup_id = django_filters.ModelMultipleChoiceFilter(
  501. field_name='fhrpgroup',
  502. queryset=FHRPGroup.objects.all(),
  503. label='FHRP group (ID)',
  504. )
  505. assigned_to_interface = django_filters.BooleanFilter(
  506. method='_assigned_to_interface',
  507. label='Is assigned to an interface',
  508. )
  509. status = django_filters.MultipleChoiceFilter(
  510. choices=IPAddressStatusChoices,
  511. null_value=None
  512. )
  513. role = django_filters.MultipleChoiceFilter(
  514. choices=IPAddressRoleChoices
  515. )
  516. class Meta:
  517. model = IPAddress
  518. fields = ['id', 'dns_name', 'description']
  519. def search(self, queryset, name, value):
  520. if not value.strip():
  521. return queryset
  522. qs_filter = (
  523. Q(dns_name__icontains=value) |
  524. Q(description__icontains=value) |
  525. Q(address__istartswith=value)
  526. )
  527. return queryset.filter(qs_filter)
  528. def search_by_parent(self, queryset, name, value):
  529. value = value.strip()
  530. if not value:
  531. return queryset
  532. try:
  533. query = str(netaddr.IPNetwork(value.strip()).cidr)
  534. return queryset.filter(address__net_host_contained=query)
  535. except (AddrFormatError, ValueError):
  536. return queryset.none()
  537. def filter_address(self, queryset, name, value):
  538. try:
  539. return queryset.filter(address__net_in=value)
  540. except ValidationError:
  541. return queryset.none()
  542. def filter_mask_length(self, queryset, name, value):
  543. if not value:
  544. return queryset
  545. return queryset.filter(address__net_mask_length=value)
  546. def filter_present_in_vrf(self, queryset, name, vrf):
  547. if vrf is None:
  548. return queryset.none
  549. return queryset.filter(
  550. Q(vrf=vrf) |
  551. Q(vrf__export_targets__in=vrf.import_targets.all())
  552. )
  553. def filter_device(self, queryset, name, value):
  554. devices = Device.objects.filter(**{'{}__in'.format(name): value})
  555. if not devices.exists():
  556. return queryset.none()
  557. interface_ids = []
  558. for device in devices:
  559. interface_ids.extend(device.vc_interfaces().values_list('id', flat=True))
  560. return queryset.filter(
  561. interface__in=interface_ids
  562. )
  563. def filter_virtual_machine(self, queryset, name, value):
  564. virtual_machines = VirtualMachine.objects.filter(**{'{}__in'.format(name): value})
  565. if not virtual_machines.exists():
  566. return queryset.none()
  567. interface_ids = []
  568. for vm in virtual_machines:
  569. interface_ids.extend(vm.interfaces.values_list('id', flat=True))
  570. return queryset.filter(
  571. vminterface__in=interface_ids
  572. )
  573. def _assigned_to_interface(self, queryset, name, value):
  574. content_types = ContentType.objects.get_for_models(Interface, VMInterface).values()
  575. if value:
  576. return queryset.filter(
  577. assigned_object_type__in=content_types,
  578. assigned_object_id__isnull=False
  579. )
  580. else:
  581. return queryset.exclude(
  582. assigned_object_type__in=content_types,
  583. assigned_object_id__isnull=False
  584. )
  585. class FHRPGroupFilterSet(NetBoxModelFilterSet):
  586. protocol = django_filters.MultipleChoiceFilter(
  587. choices=FHRPGroupProtocolChoices
  588. )
  589. auth_type = django_filters.MultipleChoiceFilter(
  590. choices=FHRPGroupAuthTypeChoices
  591. )
  592. related_ip = django_filters.ModelMultipleChoiceFilter(
  593. queryset=IPAddress.objects.all(),
  594. method='filter_related_ip'
  595. )
  596. class Meta:
  597. model = FHRPGroup
  598. fields = ['id', 'group_id', 'auth_key']
  599. def search(self, queryset, name, value):
  600. if not value.strip():
  601. return queryset
  602. return queryset.filter(
  603. Q(description__icontains=value)
  604. )
  605. def filter_related_ip(self, queryset, name, value):
  606. """
  607. Filter by VRF & prefix of assigned IP addresses.
  608. """
  609. ip_filter = Q()
  610. for ipaddress in value:
  611. if ipaddress.vrf:
  612. q = Q(
  613. ip_addresses__address__net_contained_or_equal=ipaddress.address,
  614. ip_addresses__vrf=ipaddress.vrf
  615. )
  616. else:
  617. q = Q(
  618. ip_addresses__address__net_contained_or_equal=ipaddress.address,
  619. ip_addresses__vrf__isnull=True
  620. )
  621. ip_filter |= q
  622. return queryset.filter(ip_filter)
  623. class FHRPGroupAssignmentFilterSet(ChangeLoggedModelFilterSet):
  624. interface_type = ContentTypeFilter()
  625. group_id = django_filters.ModelMultipleChoiceFilter(
  626. queryset=FHRPGroup.objects.all(),
  627. label='Group (ID)',
  628. )
  629. device = MultiValueCharFilter(
  630. method='filter_device',
  631. field_name='name',
  632. label='Device (name)',
  633. )
  634. device_id = MultiValueNumberFilter(
  635. method='filter_device',
  636. field_name='pk',
  637. label='Device (ID)',
  638. )
  639. virtual_machine = MultiValueCharFilter(
  640. method='filter_virtual_machine',
  641. field_name='name',
  642. label='Virtual machine (name)',
  643. )
  644. virtual_machine_id = MultiValueNumberFilter(
  645. method='filter_virtual_machine',
  646. field_name='pk',
  647. label='Virtual machine (ID)',
  648. )
  649. class Meta:
  650. model = FHRPGroupAssignment
  651. fields = ['id', 'group_id', 'interface_type', 'interface_id', 'priority']
  652. def filter_device(self, queryset, name, value):
  653. devices = Device.objects.filter(**{f'{name}__in': value})
  654. if not devices.exists():
  655. return queryset.none()
  656. interface_ids = []
  657. for device in devices:
  658. interface_ids.extend(device.vc_interfaces().values_list('id', flat=True))
  659. return queryset.filter(
  660. Q(interface_type=ContentType.objects.get_for_model(Interface), interface_id__in=interface_ids)
  661. )
  662. def filter_virtual_machine(self, queryset, name, value):
  663. virtual_machines = VirtualMachine.objects.filter(**{f'{name}__in': value})
  664. if not virtual_machines.exists():
  665. return queryset.none()
  666. interface_ids = []
  667. for vm in virtual_machines:
  668. interface_ids.extend(vm.interfaces.values_list('id', flat=True))
  669. return queryset.filter(
  670. Q(interface_type=ContentType.objects.get_for_model(VMInterface), interface_id__in=interface_ids)
  671. )
  672. class VLANGroupFilterSet(OrganizationalModelFilterSet):
  673. scope_type = ContentTypeFilter()
  674. region = django_filters.NumberFilter(
  675. method='filter_scope'
  676. )
  677. sitegroup = django_filters.NumberFilter(
  678. method='filter_scope'
  679. )
  680. site = django_filters.NumberFilter(
  681. method='filter_scope'
  682. )
  683. location = django_filters.NumberFilter(
  684. method='filter_scope'
  685. )
  686. rack = django_filters.NumberFilter(
  687. method='filter_scope'
  688. )
  689. clustergroup = django_filters.NumberFilter(
  690. method='filter_scope'
  691. )
  692. cluster = django_filters.NumberFilter(
  693. method='filter_scope'
  694. )
  695. class Meta:
  696. model = VLANGroup
  697. fields = ['id', 'name', 'slug', 'min_vid', 'max_vid', 'description', 'scope_id']
  698. def search(self, queryset, name, value):
  699. if not value.strip():
  700. return queryset
  701. qs_filter = (
  702. Q(name__icontains=value) |
  703. Q(description__icontains=value)
  704. )
  705. return queryset.filter(qs_filter)
  706. def filter_scope(self, queryset, name, value):
  707. return queryset.filter(
  708. scope_type=ContentType.objects.get(model=name),
  709. scope_id=value
  710. )
  711. class VLANFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
  712. region_id = TreeNodeMultipleChoiceFilter(
  713. queryset=Region.objects.all(),
  714. field_name='site__region',
  715. lookup_expr='in',
  716. label='Region (ID)',
  717. )
  718. region = TreeNodeMultipleChoiceFilter(
  719. queryset=Region.objects.all(),
  720. field_name='site__region',
  721. lookup_expr='in',
  722. to_field_name='slug',
  723. label='Region (slug)',
  724. )
  725. site_group_id = TreeNodeMultipleChoiceFilter(
  726. queryset=SiteGroup.objects.all(),
  727. field_name='site__group',
  728. lookup_expr='in',
  729. label='Site group (ID)',
  730. )
  731. site_group = TreeNodeMultipleChoiceFilter(
  732. queryset=SiteGroup.objects.all(),
  733. field_name='site__group',
  734. lookup_expr='in',
  735. to_field_name='slug',
  736. label='Site group (slug)',
  737. )
  738. site_id = django_filters.ModelMultipleChoiceFilter(
  739. queryset=Site.objects.all(),
  740. label='Site (ID)',
  741. )
  742. site = django_filters.ModelMultipleChoiceFilter(
  743. field_name='site__slug',
  744. queryset=Site.objects.all(),
  745. to_field_name='slug',
  746. label='Site (slug)',
  747. )
  748. group_id = django_filters.ModelMultipleChoiceFilter(
  749. queryset=VLANGroup.objects.all(),
  750. label='Group (ID)',
  751. )
  752. group = django_filters.ModelMultipleChoiceFilter(
  753. field_name='group__slug',
  754. queryset=VLANGroup.objects.all(),
  755. to_field_name='slug',
  756. label='Group',
  757. )
  758. role_id = django_filters.ModelMultipleChoiceFilter(
  759. queryset=Role.objects.all(),
  760. label='Role (ID)',
  761. )
  762. role = django_filters.ModelMultipleChoiceFilter(
  763. field_name='role__slug',
  764. queryset=Role.objects.all(),
  765. to_field_name='slug',
  766. label='Role (slug)',
  767. )
  768. status = django_filters.MultipleChoiceFilter(
  769. choices=VLANStatusChoices,
  770. null_value=None
  771. )
  772. available_on_device = django_filters.ModelChoiceFilter(
  773. queryset=Device.objects.all(),
  774. method='get_for_device'
  775. )
  776. available_on_virtualmachine = django_filters.ModelChoiceFilter(
  777. queryset=VirtualMachine.objects.all(),
  778. method='get_for_virtualmachine'
  779. )
  780. class Meta:
  781. model = VLAN
  782. fields = ['id', 'vid', 'name', 'description']
  783. def search(self, queryset, name, value):
  784. if not value.strip():
  785. return queryset
  786. qs_filter = Q(name__icontains=value) | Q(description__icontains=value)
  787. try:
  788. qs_filter |= Q(vid=int(value.strip()))
  789. except ValueError:
  790. pass
  791. return queryset.filter(qs_filter)
  792. def get_for_device(self, queryset, name, value):
  793. return queryset.get_for_device(value)
  794. def get_for_virtualmachine(self, queryset, name, value):
  795. return queryset.get_for_virtualmachine(value)
  796. class ServiceTemplateFilterSet(NetBoxModelFilterSet):
  797. port = NumericArrayFilter(
  798. field_name='ports',
  799. lookup_expr='contains'
  800. )
  801. class Meta:
  802. model = ServiceTemplate
  803. fields = ['id', 'name', 'protocol']
  804. def search(self, queryset, name, value):
  805. if not value.strip():
  806. return queryset
  807. qs_filter = Q(name__icontains=value) | Q(description__icontains=value)
  808. return queryset.filter(qs_filter)
  809. class ServiceFilterSet(NetBoxModelFilterSet):
  810. device_id = django_filters.ModelMultipleChoiceFilter(
  811. queryset=Device.objects.all(),
  812. label='Device (ID)',
  813. )
  814. device = django_filters.ModelMultipleChoiceFilter(
  815. field_name='device__name',
  816. queryset=Device.objects.all(),
  817. to_field_name='name',
  818. label='Device (name)',
  819. )
  820. virtual_machine_id = django_filters.ModelMultipleChoiceFilter(
  821. queryset=VirtualMachine.objects.all(),
  822. label='Virtual machine (ID)',
  823. )
  824. virtual_machine = django_filters.ModelMultipleChoiceFilter(
  825. field_name='virtual_machine__name',
  826. queryset=VirtualMachine.objects.all(),
  827. to_field_name='name',
  828. label='Virtual machine (name)',
  829. )
  830. port = NumericArrayFilter(
  831. field_name='ports',
  832. lookup_expr='contains'
  833. )
  834. class Meta:
  835. model = Service
  836. fields = ['id', 'name', 'protocol', 'description']
  837. def search(self, queryset, name, value):
  838. if not value.strip():
  839. return queryset
  840. qs_filter = Q(name__icontains=value) | Q(description__icontains=value)
  841. return queryset.filter(qs_filter)