filtersets.py 35 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127
  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) | Q(start_address__contains=value) | Q(end_address__contains=value)
  406. try:
  407. ipaddress = str(netaddr.IPNetwork(value.strip()))
  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. l2vpn_id = django_filters.ModelMultipleChoiceFilter(
  787. field_name='l2vpn_terminations__l2vpn',
  788. queryset=L2VPN.objects.all(),
  789. label=_('L2VPN (ID)'),
  790. )
  791. l2vpn = django_filters.ModelMultipleChoiceFilter(
  792. field_name='l2vpn_terminations__l2vpn__identifier',
  793. queryset=L2VPN.objects.all(),
  794. to_field_name='identifier',
  795. label=_('L2VPN'),
  796. )
  797. class Meta:
  798. model = VLAN
  799. fields = ['id', 'vid', 'name', 'description']
  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. try:
  805. qs_filter |= Q(vid=int(value.strip()))
  806. except ValueError:
  807. pass
  808. return queryset.filter(qs_filter)
  809. def get_for_device(self, queryset, name, value):
  810. return queryset.get_for_device(value)
  811. def get_for_virtualmachine(self, queryset, name, value):
  812. return queryset.get_for_virtualmachine(value)
  813. class ServiceTemplateFilterSet(NetBoxModelFilterSet):
  814. port = NumericArrayFilter(
  815. field_name='ports',
  816. lookup_expr='contains'
  817. )
  818. class Meta:
  819. model = ServiceTemplate
  820. fields = ['id', 'name', 'protocol']
  821. def search(self, queryset, name, value):
  822. if not value.strip():
  823. return queryset
  824. qs_filter = Q(name__icontains=value) | Q(description__icontains=value)
  825. return queryset.filter(qs_filter)
  826. class ServiceFilterSet(NetBoxModelFilterSet):
  827. device_id = django_filters.ModelMultipleChoiceFilter(
  828. queryset=Device.objects.all(),
  829. label=_('Device (ID)'),
  830. )
  831. device = django_filters.ModelMultipleChoiceFilter(
  832. field_name='device__name',
  833. queryset=Device.objects.all(),
  834. to_field_name='name',
  835. label=_('Device (name)'),
  836. )
  837. virtual_machine_id = django_filters.ModelMultipleChoiceFilter(
  838. queryset=VirtualMachine.objects.all(),
  839. label=_('Virtual machine (ID)'),
  840. )
  841. virtual_machine = django_filters.ModelMultipleChoiceFilter(
  842. field_name='virtual_machine__name',
  843. queryset=VirtualMachine.objects.all(),
  844. to_field_name='name',
  845. label=_('Virtual machine (name)'),
  846. )
  847. ipaddress_id = django_filters.ModelMultipleChoiceFilter(
  848. field_name='ipaddresses',
  849. queryset=IPAddress.objects.all(),
  850. label=_('IP address (ID)'),
  851. )
  852. ipaddress = django_filters.ModelMultipleChoiceFilter(
  853. field_name='ipaddresses__address',
  854. queryset=IPAddress.objects.all(),
  855. to_field_name='address',
  856. label=_('IP address'),
  857. )
  858. port = NumericArrayFilter(
  859. field_name='ports',
  860. lookup_expr='contains'
  861. )
  862. class Meta:
  863. model = Service
  864. fields = ['id', 'name', 'protocol', 'description']
  865. def search(self, queryset, name, value):
  866. if not value.strip():
  867. return queryset
  868. qs_filter = Q(name__icontains=value) | Q(description__icontains=value)
  869. return queryset.filter(qs_filter)
  870. #
  871. # L2VPN
  872. #
  873. class L2VPNFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
  874. type = django_filters.MultipleChoiceFilter(
  875. choices=L2VPNTypeChoices,
  876. null_value=None
  877. )
  878. import_target_id = django_filters.ModelMultipleChoiceFilter(
  879. field_name='import_targets',
  880. queryset=RouteTarget.objects.all(),
  881. label=_('Import target'),
  882. )
  883. import_target = django_filters.ModelMultipleChoiceFilter(
  884. field_name='import_targets__name',
  885. queryset=RouteTarget.objects.all(),
  886. to_field_name='name',
  887. label=_('Import target (name)'),
  888. )
  889. export_target_id = django_filters.ModelMultipleChoiceFilter(
  890. field_name='export_targets',
  891. queryset=RouteTarget.objects.all(),
  892. label=_('Export target'),
  893. )
  894. export_target = django_filters.ModelMultipleChoiceFilter(
  895. field_name='export_targets__name',
  896. queryset=RouteTarget.objects.all(),
  897. to_field_name='name',
  898. label=_('Export target (name)'),
  899. )
  900. class Meta:
  901. model = L2VPN
  902. fields = ['id', 'identifier', 'name', 'slug', 'type', 'description']
  903. def search(self, queryset, name, value):
  904. if not value.strip():
  905. return queryset
  906. qs_filter = Q(name__icontains=value) | Q(description__icontains=value)
  907. try:
  908. qs_filter |= Q(identifier=int(value))
  909. except ValueError:
  910. pass
  911. return queryset.filter(qs_filter)
  912. class L2VPNTerminationFilterSet(NetBoxModelFilterSet):
  913. l2vpn_id = django_filters.ModelMultipleChoiceFilter(
  914. queryset=L2VPN.objects.all(),
  915. label=_('L2VPN (ID)'),
  916. )
  917. l2vpn = django_filters.ModelMultipleChoiceFilter(
  918. field_name='l2vpn__slug',
  919. queryset=L2VPN.objects.all(),
  920. to_field_name='slug',
  921. label=_('L2VPN (slug)'),
  922. )
  923. region = MultiValueCharFilter(
  924. method='filter_region',
  925. field_name='slug',
  926. label=_('Region (slug)'),
  927. )
  928. region_id = MultiValueNumberFilter(
  929. method='filter_region',
  930. field_name='pk',
  931. label=_('Region (ID)'),
  932. )
  933. site = MultiValueCharFilter(
  934. method='filter_site',
  935. field_name='slug',
  936. label=_('Site (slug)'),
  937. )
  938. site_id = MultiValueNumberFilter(
  939. method='filter_site',
  940. field_name='pk',
  941. label=_('Site (ID)'),
  942. )
  943. device = django_filters.ModelMultipleChoiceFilter(
  944. field_name='interface__device__name',
  945. queryset=Device.objects.all(),
  946. to_field_name='name',
  947. label=_('Device (name)'),
  948. )
  949. device_id = django_filters.ModelMultipleChoiceFilter(
  950. field_name='interface__device',
  951. queryset=Device.objects.all(),
  952. label=_('Device (ID)'),
  953. )
  954. virtual_machine = django_filters.ModelMultipleChoiceFilter(
  955. field_name='vminterface__virtual_machine__name',
  956. queryset=VirtualMachine.objects.all(),
  957. to_field_name='name',
  958. label=_('Virtual machine (name)'),
  959. )
  960. virtual_machine_id = django_filters.ModelMultipleChoiceFilter(
  961. field_name='vminterface__virtual_machine',
  962. queryset=VirtualMachine.objects.all(),
  963. label=_('Virtual machine (ID)'),
  964. )
  965. interface = django_filters.ModelMultipleChoiceFilter(
  966. field_name='interface__name',
  967. queryset=Interface.objects.all(),
  968. to_field_name='name',
  969. label=_('Interface (name)'),
  970. )
  971. interface_id = django_filters.ModelMultipleChoiceFilter(
  972. field_name='interface',
  973. queryset=Interface.objects.all(),
  974. label=_('Interface (ID)'),
  975. )
  976. vminterface = django_filters.ModelMultipleChoiceFilter(
  977. field_name='vminterface__name',
  978. queryset=VMInterface.objects.all(),
  979. to_field_name='name',
  980. label=_('VM interface (name)'),
  981. )
  982. vminterface_id = django_filters.ModelMultipleChoiceFilter(
  983. field_name='vminterface',
  984. queryset=VMInterface.objects.all(),
  985. label=_('VM Interface (ID)'),
  986. )
  987. vlan = django_filters.ModelMultipleChoiceFilter(
  988. field_name='vlan__name',
  989. queryset=VLAN.objects.all(),
  990. to_field_name='name',
  991. label=_('VLAN (name)'),
  992. )
  993. vlan_vid = django_filters.NumberFilter(
  994. field_name='vlan__vid',
  995. label=_('VLAN number (1-4094)'),
  996. )
  997. vlan_id = django_filters.ModelMultipleChoiceFilter(
  998. field_name='vlan',
  999. queryset=VLAN.objects.all(),
  1000. label=_('VLAN (ID)'),
  1001. )
  1002. assigned_object_type = ContentTypeFilter()
  1003. class Meta:
  1004. model = L2VPNTermination
  1005. fields = ('id', 'assigned_object_type_id')
  1006. def search(self, queryset, name, value):
  1007. if not value.strip():
  1008. return queryset
  1009. qs_filter = Q(l2vpn__name__icontains=value)
  1010. return queryset.filter(qs_filter)
  1011. def filter_assigned_object(self, queryset, name, value):
  1012. qs = queryset.filter(
  1013. Q(**{'{}__in'.format(name): value})
  1014. )
  1015. return qs
  1016. def filter_site(self, queryset, name, value):
  1017. qs = queryset.filter(
  1018. Q(
  1019. Q(**{'vlan__site__{}__in'.format(name): value}) |
  1020. Q(**{'interface__device__site__{}__in'.format(name): value}) |
  1021. Q(**{'vminterface__virtual_machine__site__{}__in'.format(name): value})
  1022. )
  1023. )
  1024. return qs
  1025. def filter_region(self, queryset, name, value):
  1026. qs = queryset.filter(
  1027. Q(
  1028. Q(**{'vlan__site__region__{}__in'.format(name): value}) |
  1029. Q(**{'interface__device__site__region__{}__in'.format(name): value}) |
  1030. Q(**{'vminterface__virtual_machine__site__region__{}__in'.format(name): value})
  1031. )
  1032. )
  1033. return qs