filtersets.py 34 KB

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