filtersets.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. import django_filters
  2. import netaddr
  3. from django.db.models import Q
  4. from django.utils.translation import gettext as _
  5. from netaddr.core import AddrFormatError
  6. from dcim.base_filtersets import ScopedFilterSet
  7. from dcim.filtersets import CommonInterfaceFilterSet
  8. from dcim.models import Device, DeviceRole, MACAddress, Platform, Region, Site, SiteGroup
  9. from extras.filtersets import LocalConfigContextFilterSet
  10. from extras.models import ConfigTemplate
  11. from ipam.filtersets import PrimaryIPFilterSet
  12. from netbox.filtersets import NetBoxModelFilterSet, OrganizationalModelFilterSet, PrimaryModelFilterSet
  13. from tenancy.filtersets import ContactModelFilterSet, TenancyFilterSet
  14. from users.filterset_mixins import OwnerFilterMixin
  15. from utilities.filters import (
  16. MultiValueCharFilter,
  17. MultiValueMACAddressFilter,
  18. NonUniqueModelMultipleChoiceFilter,
  19. TreeNodeMultipleChoiceFilter,
  20. )
  21. from utilities.filtersets import register_filterset
  22. from .choices import *
  23. from .models import *
  24. __all__ = (
  25. 'ClusterFilterSet',
  26. 'ClusterGroupFilterSet',
  27. 'ClusterTypeFilterSet',
  28. 'VMInterfaceFilterSet',
  29. 'VirtualDiskFilterSet',
  30. 'VirtualMachineFilterSet',
  31. 'VirtualMachineTypeFilterSet',
  32. )
  33. @register_filterset
  34. class ClusterTypeFilterSet(OrganizationalModelFilterSet):
  35. class Meta:
  36. model = ClusterType
  37. fields = ('id', 'name', 'slug', 'description')
  38. @register_filterset
  39. class ClusterGroupFilterSet(OrganizationalModelFilterSet, ContactModelFilterSet):
  40. class Meta:
  41. model = ClusterGroup
  42. fields = ('id', 'name', 'slug', 'description')
  43. @register_filterset
  44. class ClusterFilterSet(PrimaryModelFilterSet, TenancyFilterSet, ScopedFilterSet, ContactModelFilterSet):
  45. group_id = django_filters.ModelMultipleChoiceFilter(
  46. queryset=ClusterGroup.objects.all(),
  47. distinct=False,
  48. label=_('Parent group (ID)'),
  49. )
  50. group = django_filters.ModelMultipleChoiceFilter(
  51. field_name='group__slug',
  52. queryset=ClusterGroup.objects.all(),
  53. distinct=False,
  54. to_field_name='slug',
  55. label=_('Parent group (slug)'),
  56. )
  57. type_id = django_filters.ModelMultipleChoiceFilter(
  58. queryset=ClusterType.objects.all(),
  59. distinct=False,
  60. label=_('Cluster type (ID)'),
  61. )
  62. type = django_filters.ModelMultipleChoiceFilter(
  63. field_name='type__slug',
  64. queryset=ClusterType.objects.all(),
  65. distinct=False,
  66. to_field_name='slug',
  67. label=_('Cluster type (slug)'),
  68. )
  69. status = django_filters.MultipleChoiceFilter(
  70. choices=ClusterStatusChoices,
  71. distinct=False,
  72. null_value=None
  73. )
  74. class Meta:
  75. model = Cluster
  76. fields = ('id', 'name', 'description', 'scope_id')
  77. def search(self, queryset, name, value):
  78. if not value.strip():
  79. return queryset
  80. return queryset.filter(
  81. Q(name__icontains=value) |
  82. Q(description__icontains=value) |
  83. Q(comments__icontains=value)
  84. )
  85. @register_filterset
  86. class VirtualMachineTypeFilterSet(PrimaryModelFilterSet):
  87. default_platform_id = TreeNodeMultipleChoiceFilter(
  88. queryset=Platform.objects.all(),
  89. field_name='default_platform',
  90. lookup_expr='in',
  91. label=_('Default platform (ID)'),
  92. )
  93. default_platform = TreeNodeMultipleChoiceFilter(
  94. queryset=Platform.objects.all(),
  95. field_name='default_platform',
  96. to_field_name='slug',
  97. lookup_expr='in',
  98. label=_('Default platform (slug)'),
  99. )
  100. class Meta:
  101. model = VirtualMachineType
  102. fields = (
  103. 'id',
  104. 'name',
  105. 'slug',
  106. 'default_vcpus',
  107. 'default_memory',
  108. 'description',
  109. 'virtual_machine_count',
  110. )
  111. def search(self, queryset, name, value):
  112. if not value.strip():
  113. return queryset
  114. return queryset.filter(
  115. Q(name__icontains=value) |
  116. Q(description__icontains=value) |
  117. Q(comments__icontains=value)
  118. )
  119. @register_filterset
  120. class VirtualMachineFilterSet(
  121. PrimaryModelFilterSet,
  122. TenancyFilterSet,
  123. ContactModelFilterSet,
  124. LocalConfigContextFilterSet,
  125. PrimaryIPFilterSet,
  126. ):
  127. virtual_machine_type_id = django_filters.ModelMultipleChoiceFilter(
  128. queryset=VirtualMachineType.objects.all(),
  129. distinct=False,
  130. label=_('Virtual machine type (ID)'),
  131. )
  132. virtual_machine_type = django_filters.ModelMultipleChoiceFilter(
  133. field_name='virtual_machine_type__slug',
  134. queryset=VirtualMachineType.objects.all(),
  135. distinct=False,
  136. to_field_name='slug',
  137. label=_('Virtual machine type (slug)'),
  138. )
  139. status = django_filters.MultipleChoiceFilter(
  140. choices=VirtualMachineStatusChoices,
  141. distinct=False,
  142. null_value=None
  143. )
  144. start_on_boot = django_filters.MultipleChoiceFilter(
  145. choices=VirtualMachineStartOnBootChoices,
  146. distinct=False,
  147. null_value=None
  148. )
  149. cluster_group_id = django_filters.ModelMultipleChoiceFilter(
  150. field_name='cluster__group',
  151. queryset=ClusterGroup.objects.all(),
  152. distinct=False,
  153. label=_('Cluster group (ID)'),
  154. )
  155. cluster_group = django_filters.ModelMultipleChoiceFilter(
  156. field_name='cluster__group__slug',
  157. queryset=ClusterGroup.objects.all(),
  158. distinct=False,
  159. to_field_name='slug',
  160. label=_('Cluster group (slug)'),
  161. )
  162. cluster_type_id = django_filters.ModelMultipleChoiceFilter(
  163. field_name='cluster__type',
  164. queryset=ClusterType.objects.all(),
  165. distinct=False,
  166. label=_('Cluster type (ID)'),
  167. )
  168. cluster_type = django_filters.ModelMultipleChoiceFilter(
  169. field_name='cluster__type__slug',
  170. queryset=ClusterType.objects.all(),
  171. distinct=False,
  172. to_field_name='slug',
  173. label=_('Cluster type (slug)'),
  174. )
  175. cluster_id = django_filters.ModelMultipleChoiceFilter(
  176. queryset=Cluster.objects.all(),
  177. distinct=False,
  178. label=_('Cluster (ID)'),
  179. )
  180. cluster = django_filters.ModelMultipleChoiceFilter(
  181. field_name='cluster__name',
  182. queryset=Cluster.objects.all(),
  183. distinct=False,
  184. to_field_name='name',
  185. label=_('Cluster'),
  186. )
  187. device_id = django_filters.ModelMultipleChoiceFilter(
  188. queryset=Device.objects.all(),
  189. distinct=False,
  190. label=_('Device (ID)'),
  191. )
  192. device = NonUniqueModelMultipleChoiceFilter(
  193. field_name='device__name',
  194. queryset=Device.objects.all(),
  195. distinct=False,
  196. to_field_name='name',
  197. label=_('Device'),
  198. )
  199. region_id = TreeNodeMultipleChoiceFilter(
  200. queryset=Region.objects.all(),
  201. field_name='site__region',
  202. lookup_expr='in',
  203. label=_('Region (ID)'),
  204. )
  205. region = TreeNodeMultipleChoiceFilter(
  206. queryset=Region.objects.all(),
  207. field_name='site__region',
  208. lookup_expr='in',
  209. to_field_name='slug',
  210. label=_('Region (slug)'),
  211. )
  212. site_group_id = TreeNodeMultipleChoiceFilter(
  213. queryset=SiteGroup.objects.all(),
  214. field_name='site__group',
  215. lookup_expr='in',
  216. label=_('Site group (ID)'),
  217. )
  218. site_group = TreeNodeMultipleChoiceFilter(
  219. queryset=SiteGroup.objects.all(),
  220. field_name='site__group',
  221. lookup_expr='in',
  222. to_field_name='slug',
  223. label=_('Site group (slug)'),
  224. )
  225. site_id = django_filters.ModelMultipleChoiceFilter(
  226. queryset=Site.objects.all(),
  227. distinct=False,
  228. label=_('Site (ID)'),
  229. )
  230. site = django_filters.ModelMultipleChoiceFilter(
  231. field_name='site__slug',
  232. queryset=Site.objects.all(),
  233. distinct=False,
  234. to_field_name='slug',
  235. label=_('Site (slug)'),
  236. )
  237. name = MultiValueCharFilter(
  238. lookup_expr='iexact'
  239. )
  240. role_id = TreeNodeMultipleChoiceFilter(
  241. queryset=DeviceRole.objects.all(),
  242. lookup_expr='in',
  243. label=_('Role (ID)'),
  244. )
  245. role = TreeNodeMultipleChoiceFilter(
  246. field_name='role',
  247. queryset=DeviceRole.objects.all(),
  248. lookup_expr='in',
  249. to_field_name='slug',
  250. label=_('Role (slug)'),
  251. )
  252. platform_id = TreeNodeMultipleChoiceFilter(
  253. queryset=Platform.objects.all(),
  254. field_name='platform',
  255. lookup_expr='in',
  256. label=_('Platform (ID)'),
  257. )
  258. platform = TreeNodeMultipleChoiceFilter(
  259. queryset=Platform.objects.all(),
  260. field_name='platform',
  261. lookup_expr='in',
  262. to_field_name='slug',
  263. label=_('Platform (slug)'),
  264. )
  265. mac_address = MultiValueMACAddressFilter(
  266. field_name='interfaces__mac_addresses__mac_address',
  267. label=_('MAC address'),
  268. )
  269. has_primary_ip = django_filters.BooleanFilter(
  270. method='_has_primary_ip',
  271. label=_('Has a primary IP'),
  272. )
  273. config_template_id = django_filters.ModelMultipleChoiceFilter(
  274. queryset=ConfigTemplate.objects.all(),
  275. distinct=False,
  276. label=_('Config template (ID)'),
  277. )
  278. class Meta:
  279. model = VirtualMachine
  280. fields = (
  281. 'id', 'cluster', 'vcpus', 'memory', 'disk', 'description', 'interface_count', 'virtual_disk_count',
  282. 'serial'
  283. )
  284. def search(self, queryset, name, value):
  285. if not value.strip():
  286. return queryset
  287. qs_filter = Q(
  288. Q(name__icontains=value) |
  289. Q(description__icontains=value) |
  290. Q(comments__icontains=value) |
  291. Q(serial__icontains=value)
  292. )
  293. # If the given value looks like an IP address, look for primary IPv4/IPv6 assignments
  294. try:
  295. ipaddress = netaddr.IPNetwork(value)
  296. if ipaddress.version == 4:
  297. qs_filter |= Q(primary_ip4__address__host__inet=ipaddress.ip)
  298. elif ipaddress.version == 6:
  299. qs_filter |= Q(primary_ip6__address__host__inet=ipaddress.ip)
  300. except (AddrFormatError, ValueError):
  301. pass
  302. return queryset.filter(qs_filter)
  303. def _has_primary_ip(self, queryset, name, value):
  304. params = Q(primary_ip4__isnull=False) | Q(primary_ip6__isnull=False)
  305. if value:
  306. return queryset.filter(params)
  307. return queryset.exclude(params)
  308. @register_filterset
  309. class VMInterfaceFilterSet(CommonInterfaceFilterSet, OwnerFilterMixin, NetBoxModelFilterSet):
  310. cluster_id = django_filters.ModelMultipleChoiceFilter(
  311. field_name='virtual_machine__cluster',
  312. queryset=Cluster.objects.all(),
  313. distinct=False,
  314. label=_('Cluster (ID)'),
  315. )
  316. cluster = django_filters.ModelMultipleChoiceFilter(
  317. field_name='virtual_machine__cluster__name',
  318. queryset=Cluster.objects.all(),
  319. distinct=False,
  320. to_field_name='name',
  321. label=_('Cluster'),
  322. )
  323. virtual_machine_id = django_filters.ModelMultipleChoiceFilter(
  324. field_name='virtual_machine',
  325. queryset=VirtualMachine.objects.all(),
  326. distinct=False,
  327. label=_('Virtual machine (ID)'),
  328. )
  329. virtual_machine = NonUniqueModelMultipleChoiceFilter(
  330. field_name='virtual_machine__name',
  331. queryset=VirtualMachine.objects.all(),
  332. distinct=False,
  333. to_field_name='name',
  334. label=_('Virtual machine'),
  335. )
  336. parent_id = django_filters.ModelMultipleChoiceFilter(
  337. field_name='parent',
  338. queryset=VMInterface.objects.all(),
  339. distinct=False,
  340. label=_('Parent interface (ID)'),
  341. )
  342. bridge_id = django_filters.ModelMultipleChoiceFilter(
  343. field_name='bridge',
  344. queryset=VMInterface.objects.all(),
  345. distinct=False,
  346. label=_('Bridged interface (ID)'),
  347. )
  348. mac_address = MultiValueMACAddressFilter(
  349. field_name='mac_addresses__mac_address',
  350. label=_('MAC address'),
  351. )
  352. primary_mac_address_id = django_filters.ModelMultipleChoiceFilter(
  353. field_name='primary_mac_address',
  354. queryset=MACAddress.objects.all(),
  355. distinct=False,
  356. label=_('Primary MAC address (ID)'),
  357. )
  358. primary_mac_address = django_filters.ModelMultipleChoiceFilter(
  359. field_name='primary_mac_address__mac_address',
  360. queryset=MACAddress.objects.all(),
  361. distinct=False,
  362. to_field_name='mac_address',
  363. label=_('Primary MAC address'),
  364. )
  365. class Meta:
  366. model = VMInterface
  367. fields = ('id', 'name', 'enabled', 'mtu', 'mode', 'description')
  368. def search(self, queryset, name, value):
  369. if not value.strip():
  370. return queryset
  371. return queryset.filter(
  372. Q(name__icontains=value) |
  373. Q(description__icontains=value)
  374. )
  375. @register_filterset
  376. class VirtualDiskFilterSet(OwnerFilterMixin, NetBoxModelFilterSet):
  377. virtual_machine_id = django_filters.ModelMultipleChoiceFilter(
  378. field_name='virtual_machine',
  379. queryset=VirtualMachine.objects.all(),
  380. distinct=False,
  381. label=_('Virtual machine (ID)'),
  382. )
  383. virtual_machine = NonUniqueModelMultipleChoiceFilter(
  384. field_name='virtual_machine__name',
  385. queryset=VirtualMachine.objects.all(),
  386. distinct=False,
  387. to_field_name='name',
  388. label=_('Virtual machine'),
  389. )
  390. class Meta:
  391. model = VirtualDisk
  392. fields = ('id', 'name', 'size', 'description')
  393. def search(self, queryset, name, value):
  394. if not value.strip():
  395. return queryset
  396. return queryset.filter(
  397. Q(name__icontains=value) |
  398. Q(description__icontains=value)
  399. )