filtersets.py 13 KB

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