filtersets.py 35 KB

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