filtersets.py 28 KB

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