views.py 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644
  1. from django.contrib import messages
  2. from django.contrib.contenttypes.models import ContentType
  3. from django.db import router, transaction
  4. from django.db.models import Prefetch, Sum
  5. from django.shortcuts import get_object_or_404, redirect, render
  6. from django.urls import reverse
  7. from django.utils.translation import gettext_lazy as _
  8. from dcim.filtersets import DeviceFilterSet
  9. from dcim.forms import DeviceFilterForm
  10. from dcim.models import Device
  11. from dcim.tables import DeviceTable
  12. from extras.views import ObjectConfigContextView, ObjectRenderConfigView
  13. from ipam.models import IPAddress, VLANGroup
  14. from ipam.tables import InterfaceVLANTable, VLANTranslationRuleTable
  15. from netbox.object_actions import (
  16. AddObject, BulkDelete, BulkEdit, BulkExport, BulkImport, BulkRename, DeleteObject, EditObject,
  17. )
  18. from netbox.views import generic
  19. from utilities.query import count_related
  20. from utilities.query_functions import CollateAsChar
  21. from utilities.views import GetRelatedModelsMixin, ViewTab, register_model_view
  22. from . import filtersets, forms, tables
  23. from .models import *
  24. from .object_actions import BulkAddComponents
  25. #
  26. # Cluster types
  27. #
  28. @register_model_view(ClusterType, 'list', path='', detail=False)
  29. class ClusterTypeListView(generic.ObjectListView):
  30. queryset = ClusterType.objects.annotate(
  31. cluster_count=count_related(Cluster, 'type')
  32. )
  33. filterset = filtersets.ClusterTypeFilterSet
  34. filterset_form = forms.ClusterTypeFilterForm
  35. table = tables.ClusterTypeTable
  36. @register_model_view(ClusterType)
  37. class ClusterTypeView(GetRelatedModelsMixin, generic.ObjectView):
  38. queryset = ClusterType.objects.all()
  39. def get_extra_context(self, request, instance):
  40. return {
  41. 'related_models': self.get_related_models(request, instance),
  42. }
  43. @register_model_view(ClusterType, 'add', detail=False)
  44. @register_model_view(ClusterType, 'edit')
  45. class ClusterTypeEditView(generic.ObjectEditView):
  46. queryset = ClusterType.objects.all()
  47. form = forms.ClusterTypeForm
  48. @register_model_view(ClusterType, 'delete')
  49. class ClusterTypeDeleteView(generic.ObjectDeleteView):
  50. queryset = ClusterType.objects.all()
  51. @register_model_view(ClusterType, 'bulk_import', path='import', detail=False)
  52. class ClusterTypeBulkImportView(generic.BulkImportView):
  53. queryset = ClusterType.objects.all()
  54. model_form = forms.ClusterTypeImportForm
  55. @register_model_view(ClusterType, 'bulk_edit', path='edit', detail=False)
  56. class ClusterTypeBulkEditView(generic.BulkEditView):
  57. queryset = ClusterType.objects.annotate(
  58. cluster_count=count_related(Cluster, 'type')
  59. )
  60. filterset = filtersets.ClusterTypeFilterSet
  61. table = tables.ClusterTypeTable
  62. form = forms.ClusterTypeBulkEditForm
  63. @register_model_view(ClusterType, 'bulk_rename', path='rename', detail=False)
  64. class ClusterTypeBulkRenameView(generic.BulkRenameView):
  65. queryset = ClusterType.objects.all()
  66. @register_model_view(ClusterType, 'bulk_delete', path='delete', detail=False)
  67. class ClusterTypeBulkDeleteView(generic.BulkDeleteView):
  68. queryset = ClusterType.objects.annotate(
  69. cluster_count=count_related(Cluster, 'type')
  70. )
  71. filterset = filtersets.ClusterTypeFilterSet
  72. table = tables.ClusterTypeTable
  73. #
  74. # Cluster groups
  75. #
  76. @register_model_view(ClusterGroup, 'list', path='', detail=False)
  77. class ClusterGroupListView(generic.ObjectListView):
  78. queryset = ClusterGroup.objects.annotate(
  79. cluster_count=count_related(Cluster, 'group')
  80. )
  81. filterset = filtersets.ClusterGroupFilterSet
  82. filterset_form = forms.ClusterGroupFilterForm
  83. table = tables.ClusterGroupTable
  84. @register_model_view(ClusterGroup)
  85. class ClusterGroupView(GetRelatedModelsMixin, generic.ObjectView):
  86. queryset = ClusterGroup.objects.all()
  87. def get_extra_context(self, request, instance):
  88. return {
  89. 'related_models': self.get_related_models(
  90. request,
  91. instance,
  92. extra=(
  93. (
  94. VLANGroup.objects.restrict(request.user, 'view').filter(
  95. scope_type=ContentType.objects.get_for_model(ClusterGroup),
  96. scope_id=instance.pk
  97. ), 'cluster_group'),
  98. ),
  99. ),
  100. }
  101. @register_model_view(ClusterGroup, 'add', detail=False)
  102. @register_model_view(ClusterGroup, 'edit')
  103. class ClusterGroupEditView(generic.ObjectEditView):
  104. queryset = ClusterGroup.objects.all()
  105. form = forms.ClusterGroupForm
  106. @register_model_view(ClusterGroup, 'delete')
  107. class ClusterGroupDeleteView(generic.ObjectDeleteView):
  108. queryset = ClusterGroup.objects.all()
  109. @register_model_view(ClusterGroup, 'bulk_import', path='import', detail=False)
  110. class ClusterGroupBulkImportView(generic.BulkImportView):
  111. queryset = ClusterGroup.objects.annotate(
  112. cluster_count=count_related(Cluster, 'group')
  113. )
  114. model_form = forms.ClusterGroupImportForm
  115. @register_model_view(ClusterGroup, 'bulk_edit', path='edit', detail=False)
  116. class ClusterGroupBulkEditView(generic.BulkEditView):
  117. queryset = ClusterGroup.objects.annotate(
  118. cluster_count=count_related(Cluster, 'group')
  119. )
  120. filterset = filtersets.ClusterGroupFilterSet
  121. table = tables.ClusterGroupTable
  122. form = forms.ClusterGroupBulkEditForm
  123. @register_model_view(ClusterGroup, 'bulk_rename', path='rename', detail=False)
  124. class ClusterGroupBulkRenameView(generic.BulkRenameView):
  125. queryset = ClusterGroup.objects.all()
  126. @register_model_view(ClusterGroup, 'bulk_delete', path='delete', detail=False)
  127. class ClusterGroupBulkDeleteView(generic.BulkDeleteView):
  128. queryset = ClusterGroup.objects.annotate(
  129. cluster_count=count_related(Cluster, 'group')
  130. )
  131. filterset = filtersets.ClusterGroupFilterSet
  132. table = tables.ClusterGroupTable
  133. #
  134. # Clusters
  135. #
  136. @register_model_view(Cluster, 'list', path='', detail=False)
  137. class ClusterListView(generic.ObjectListView):
  138. permission_required = 'virtualization.view_cluster'
  139. queryset = Cluster.objects.annotate(
  140. device_count=count_related(Device, 'cluster'),
  141. vm_count=count_related(VirtualMachine, 'cluster')
  142. )
  143. table = tables.ClusterTable
  144. filterset = filtersets.ClusterFilterSet
  145. filterset_form = forms.ClusterFilterForm
  146. @register_model_view(Cluster)
  147. class ClusterView(GetRelatedModelsMixin, generic.ObjectView):
  148. queryset = Cluster.objects.all()
  149. def get_extra_context(self, request, instance):
  150. return {
  151. **instance.virtual_machines.aggregate(
  152. vcpus_sum=Sum('vcpus'),
  153. memory_sum=Sum('memory'),
  154. disk_sum=Sum('disk')
  155. ),
  156. 'related_models': self.get_related_models(
  157. request,
  158. instance,
  159. omit=(),
  160. extra=(
  161. (VLANGroup.objects.restrict(request.user, 'view').filter(
  162. scope_type=ContentType.objects.get_for_model(Cluster),
  163. scope_id=instance.pk
  164. ), 'cluster'),
  165. )
  166. ),
  167. }
  168. @register_model_view(Cluster, 'virtualmachines', path='virtual-machines')
  169. class ClusterVirtualMachinesView(generic.ObjectChildrenView):
  170. queryset = Cluster.objects.all()
  171. child_model = VirtualMachine
  172. table = tables.VirtualMachineTable
  173. filterset = filtersets.VirtualMachineFilterSet
  174. filterset_form = forms.VirtualMachineFilterForm
  175. actions = (EditObject, DeleteObject, BulkEdit)
  176. tab = ViewTab(
  177. label=_('Virtual Machines'),
  178. badge=lambda obj: obj.virtual_machines.count(),
  179. permission='virtualization.view_virtualmachine',
  180. weight=500
  181. )
  182. def get_children(self, request, parent):
  183. return VirtualMachine.objects.restrict(request.user, 'view').filter(cluster=parent)
  184. @register_model_view(Cluster, 'devices')
  185. class ClusterDevicesView(generic.ObjectChildrenView):
  186. queryset = Cluster.objects.all()
  187. child_model = Device
  188. table = DeviceTable
  189. filterset = DeviceFilterSet
  190. filterset_form = DeviceFilterForm
  191. actions = (EditObject, DeleteObject, BulkEdit)
  192. tab = ViewTab(
  193. label=_('Devices'),
  194. badge=lambda obj: obj.devices.count(),
  195. permission='virtualization.view_virtualmachine',
  196. weight=600
  197. )
  198. def get_children(self, request, parent):
  199. return Device.objects.restrict(request.user, 'view').filter(cluster=parent)
  200. @register_model_view(Cluster, 'add', detail=False)
  201. @register_model_view(Cluster, 'edit')
  202. class ClusterEditView(generic.ObjectEditView):
  203. queryset = Cluster.objects.all()
  204. form = forms.ClusterForm
  205. @register_model_view(Cluster, 'delete')
  206. class ClusterDeleteView(generic.ObjectDeleteView):
  207. queryset = Cluster.objects.all()
  208. @register_model_view(Cluster, 'bulk_import', path='import', detail=False)
  209. class ClusterBulkImportView(generic.BulkImportView):
  210. queryset = Cluster.objects.all()
  211. model_form = forms.ClusterImportForm
  212. @register_model_view(Cluster, 'bulk_edit', path='edit', detail=False)
  213. class ClusterBulkEditView(generic.BulkEditView):
  214. queryset = Cluster.objects.all()
  215. filterset = filtersets.ClusterFilterSet
  216. table = tables.ClusterTable
  217. form = forms.ClusterBulkEditForm
  218. @register_model_view(Cluster, 'bulk_rename', path='rename', detail=False)
  219. class ClusterBulkRenameView(generic.BulkRenameView):
  220. queryset = Cluster.objects.all()
  221. @register_model_view(Cluster, 'bulk_delete', path='delete', detail=False)
  222. class ClusterBulkDeleteView(generic.BulkDeleteView):
  223. queryset = Cluster.objects.all()
  224. filterset = filtersets.ClusterFilterSet
  225. table = tables.ClusterTable
  226. @register_model_view(Cluster, 'add_devices', path='devices/add')
  227. class ClusterAddDevicesView(generic.ObjectEditView):
  228. queryset = Cluster.objects.all()
  229. form = forms.ClusterAddDevicesForm
  230. template_name = 'virtualization/cluster_add_devices.html'
  231. def get(self, request, pk):
  232. cluster = get_object_or_404(self.queryset, pk=pk)
  233. form = self.form(cluster, initial=request.GET)
  234. return render(request, self.template_name, {
  235. 'cluster': cluster,
  236. 'form': form,
  237. 'return_url': reverse('virtualization:cluster', kwargs={'pk': pk}),
  238. })
  239. def post(self, request, pk):
  240. cluster = get_object_or_404(self.queryset, pk=pk)
  241. form = self.form(cluster, request.POST)
  242. if form.is_valid():
  243. device_pks = form.cleaned_data['devices']
  244. with transaction.atomic(using=router.db_for_write(Device)):
  245. # Assign the selected Devices to the Cluster
  246. for device in Device.objects.filter(pk__in=device_pks):
  247. device.cluster = cluster
  248. device.save()
  249. messages.success(request, _("Added {count} devices to cluster {cluster}").format(
  250. count=len(device_pks),
  251. cluster=cluster
  252. ))
  253. return redirect(cluster.get_absolute_url())
  254. return render(request, self.template_name, {
  255. 'cluster': cluster,
  256. 'form': form,
  257. 'return_url': cluster.get_absolute_url(),
  258. })
  259. #
  260. # Virtual machines
  261. #
  262. @register_model_view(VirtualMachine, 'list', path='', detail=False)
  263. class VirtualMachineListView(generic.ObjectListView):
  264. queryset = VirtualMachine.objects.prefetch_related('primary_ip4', 'primary_ip6')
  265. filterset = filtersets.VirtualMachineFilterSet
  266. filterset_form = forms.VirtualMachineFilterForm
  267. table = tables.VirtualMachineTable
  268. actions = (AddObject, BulkImport, BulkExport, BulkAddComponents, BulkEdit, BulkRename, BulkDelete)
  269. @register_model_view(VirtualMachine)
  270. class VirtualMachineView(generic.ObjectView):
  271. queryset = VirtualMachine.objects.all()
  272. @register_model_view(VirtualMachine, 'interfaces')
  273. class VirtualMachineInterfacesView(generic.ObjectChildrenView):
  274. queryset = VirtualMachine.objects.all()
  275. child_model = VMInterface
  276. table = tables.VirtualMachineVMInterfaceTable
  277. filterset = filtersets.VMInterfaceFilterSet
  278. filterset_form = forms.VMInterfaceFilterForm
  279. actions = (EditObject, DeleteObject, BulkEdit, BulkRename, BulkDelete)
  280. tab = ViewTab(
  281. label=_('Interfaces'),
  282. badge=lambda obj: obj.interface_count,
  283. permission='virtualization.view_vminterface',
  284. weight=500
  285. )
  286. def get_children(self, request, parent):
  287. return parent.interfaces.restrict(request.user, 'view').prefetch_related(
  288. Prefetch('ip_addresses', queryset=IPAddress.objects.restrict(request.user)),
  289. 'tags',
  290. )
  291. @register_model_view(VirtualMachine, 'disks')
  292. class VirtualMachineVirtualDisksView(generic.ObjectChildrenView):
  293. queryset = VirtualMachine.objects.all()
  294. child_model = VirtualDisk
  295. table = tables.VirtualMachineVirtualDiskTable
  296. filterset = filtersets.VirtualDiskFilterSet
  297. filterset_form = forms.VirtualDiskFilterForm
  298. actions = (EditObject, DeleteObject, BulkEdit, BulkRename, BulkDelete)
  299. tab = ViewTab(
  300. label=_('Virtual Disks'),
  301. badge=lambda obj: obj.virtual_disk_count,
  302. permission='virtualization.view_virtualdisk',
  303. weight=500
  304. )
  305. def get_children(self, request, parent):
  306. return parent.virtualdisks.restrict(request.user, 'view').prefetch_related('tags')
  307. @register_model_view(VirtualMachine, 'configcontext', path='config-context')
  308. class VirtualMachineConfigContextView(ObjectConfigContextView):
  309. queryset = VirtualMachine.objects.annotate_config_context_data()
  310. base_template = 'virtualization/virtualmachine.html'
  311. tab = ViewTab(
  312. label=_('Config Context'),
  313. weight=2000
  314. )
  315. @register_model_view(VirtualMachine, 'render-config')
  316. class VirtualMachineRenderConfigView(ObjectRenderConfigView):
  317. queryset = VirtualMachine.objects.all()
  318. base_template = 'virtualization/virtualmachine/base.html'
  319. tab = ViewTab(
  320. label=_('Render Config'),
  321. weight=2100,
  322. )
  323. @register_model_view(VirtualMachine, 'add', detail=False)
  324. @register_model_view(VirtualMachine, 'edit')
  325. class VirtualMachineEditView(generic.ObjectEditView):
  326. queryset = VirtualMachine.objects.all()
  327. form = forms.VirtualMachineForm
  328. @register_model_view(VirtualMachine, 'delete')
  329. class VirtualMachineDeleteView(generic.ObjectDeleteView):
  330. queryset = VirtualMachine.objects.all()
  331. @register_model_view(VirtualMachine, 'bulk_import', path='import', detail=False)
  332. class VirtualMachineBulkImportView(generic.BulkImportView):
  333. queryset = VirtualMachine.objects.all()
  334. model_form = forms.VirtualMachineImportForm
  335. @register_model_view(VirtualMachine, 'bulk_edit', path='edit', detail=False)
  336. class VirtualMachineBulkEditView(generic.BulkEditView):
  337. queryset = VirtualMachine.objects.prefetch_related('primary_ip4', 'primary_ip6')
  338. filterset = filtersets.VirtualMachineFilterSet
  339. table = tables.VirtualMachineTable
  340. form = forms.VirtualMachineBulkEditForm
  341. @register_model_view(VirtualMachine, 'bulk_rename', path='rename', detail=False)
  342. class VirtualMachineBulkRenameView(generic.BulkRenameView):
  343. queryset = VirtualMachine.objects.all()
  344. @register_model_view(VirtualMachine, 'bulk_delete', path='delete', detail=False)
  345. class VirtualMachineBulkDeleteView(generic.BulkDeleteView):
  346. queryset = VirtualMachine.objects.prefetch_related('primary_ip4', 'primary_ip6')
  347. filterset = filtersets.VirtualMachineFilterSet
  348. table = tables.VirtualMachineTable
  349. #
  350. # VM interfaces
  351. #
  352. @register_model_view(VMInterface, 'list', path='', detail=False)
  353. class VMInterfaceListView(generic.ObjectListView):
  354. queryset = VMInterface.objects.all()
  355. filterset = filtersets.VMInterfaceFilterSet
  356. filterset_form = forms.VMInterfaceFilterForm
  357. table = tables.VMInterfaceTable
  358. @register_model_view(VMInterface)
  359. class VMInterfaceView(generic.ObjectView):
  360. queryset = VMInterface.objects.all()
  361. def get_extra_context(self, request, instance):
  362. # Get child interfaces
  363. child_interfaces = VMInterface.objects.restrict(request.user, 'view').filter(parent=instance)
  364. child_interfaces_tables = tables.VMInterfaceTable(
  365. child_interfaces,
  366. exclude=('virtual_machine',),
  367. orderable=False
  368. )
  369. child_interfaces_tables.configure(request)
  370. # Get VLAN translation rules
  371. vlan_translation_table = None
  372. if instance.vlan_translation_policy:
  373. vlan_translation_table = VLANTranslationRuleTable(
  374. data=instance.vlan_translation_policy.rules.all(),
  375. orderable=False
  376. )
  377. vlan_translation_table.configure(request)
  378. # Get assigned VLANs and annotate whether each is tagged or untagged
  379. vlans = []
  380. if instance.untagged_vlan is not None:
  381. vlans.append(instance.untagged_vlan)
  382. vlans[0].tagged = False
  383. for vlan in instance.tagged_vlans.restrict(request.user).prefetch_related('site', 'group', 'tenant', 'role'):
  384. vlan.tagged = True
  385. vlans.append(vlan)
  386. vlan_table = InterfaceVLANTable(
  387. interface=instance,
  388. data=vlans,
  389. orderable=False
  390. )
  391. vlan_table.configure(request)
  392. return {
  393. 'child_interfaces_table': child_interfaces_tables,
  394. 'vlan_table': vlan_table,
  395. 'vlan_translation_table': vlan_translation_table,
  396. }
  397. @register_model_view(VMInterface, 'add', detail=False)
  398. class VMInterfaceCreateView(generic.ComponentCreateView):
  399. queryset = VMInterface.objects.all()
  400. form = forms.VMInterfaceCreateForm
  401. model_form = forms.VMInterfaceForm
  402. @register_model_view(VMInterface, 'edit')
  403. class VMInterfaceEditView(generic.ObjectEditView):
  404. queryset = VMInterface.objects.all()
  405. form = forms.VMInterfaceForm
  406. @register_model_view(VMInterface, 'delete')
  407. class VMInterfaceDeleteView(generic.ObjectDeleteView):
  408. queryset = VMInterface.objects.all()
  409. @register_model_view(VMInterface, 'bulk_import', path='import', detail=False)
  410. class VMInterfaceBulkImportView(generic.BulkImportView):
  411. queryset = VMInterface.objects.all()
  412. model_form = forms.VMInterfaceImportForm
  413. @register_model_view(VMInterface, 'bulk_edit', path='edit', detail=False)
  414. class VMInterfaceBulkEditView(generic.BulkEditView):
  415. queryset = VMInterface.objects.all()
  416. filterset = filtersets.VMInterfaceFilterSet
  417. table = tables.VMInterfaceTable
  418. form = forms.VMInterfaceBulkEditForm
  419. @register_model_view(VMInterface, 'bulk_rename', path='rename', detail=False)
  420. class VMInterfaceBulkRenameView(generic.BulkRenameView):
  421. queryset = VMInterface.objects.all()
  422. form = forms.VMInterfaceBulkRenameForm
  423. @register_model_view(VMInterface, 'bulk_delete', path='delete', detail=False)
  424. class VMInterfaceBulkDeleteView(generic.BulkDeleteView):
  425. # Ensure child interfaces are deleted prior to their parents
  426. queryset = VMInterface.objects.order_by('virtual_machine', 'parent', CollateAsChar('_name'))
  427. filterset = filtersets.VMInterfaceFilterSet
  428. table = tables.VMInterfaceTable
  429. #
  430. # Virtual disks
  431. #
  432. @register_model_view(VirtualDisk, 'list', path='', detail=False)
  433. class VirtualDiskListView(generic.ObjectListView):
  434. queryset = VirtualDisk.objects.all()
  435. filterset = filtersets.VirtualDiskFilterSet
  436. filterset_form = forms.VirtualDiskFilterForm
  437. table = tables.VirtualDiskTable
  438. @register_model_view(VirtualDisk)
  439. class VirtualDiskView(generic.ObjectView):
  440. queryset = VirtualDisk.objects.all()
  441. @register_model_view(VirtualDisk, 'add', detail=False)
  442. class VirtualDiskCreateView(generic.ComponentCreateView):
  443. queryset = VirtualDisk.objects.all()
  444. form = forms.VirtualDiskCreateForm
  445. model_form = forms.VirtualDiskForm
  446. @register_model_view(VirtualDisk, 'edit')
  447. class VirtualDiskEditView(generic.ObjectEditView):
  448. queryset = VirtualDisk.objects.all()
  449. form = forms.VirtualDiskForm
  450. @register_model_view(VirtualDisk, 'delete')
  451. class VirtualDiskDeleteView(generic.ObjectDeleteView):
  452. queryset = VirtualDisk.objects.all()
  453. @register_model_view(VirtualDisk, 'bulk_import', path='import', detail=False)
  454. class VirtualDiskBulkImportView(generic.BulkImportView):
  455. queryset = VirtualDisk.objects.all()
  456. model_form = forms.VirtualDiskImportForm
  457. @register_model_view(VirtualDisk, 'bulk_edit', path='edit', detail=False)
  458. class VirtualDiskBulkEditView(generic.BulkEditView):
  459. queryset = VirtualDisk.objects.all()
  460. filterset = filtersets.VirtualDiskFilterSet
  461. table = tables.VirtualDiskTable
  462. form = forms.VirtualDiskBulkEditForm
  463. @register_model_view(VirtualDisk, 'bulk_rename', path='rename', detail=False)
  464. class VirtualDiskBulkRenameView(generic.BulkRenameView):
  465. queryset = VirtualDisk.objects.all()
  466. form = forms.VirtualDiskBulkRenameForm
  467. @register_model_view(VirtualDisk, 'bulk_delete', path='delete', detail=False)
  468. class VirtualDiskBulkDeleteView(generic.BulkDeleteView):
  469. queryset = VirtualDisk.objects.all()
  470. filterset = filtersets.VirtualDiskFilterSet
  471. table = tables.VirtualDiskTable
  472. #
  473. # Bulk Device component creation
  474. #
  475. class VirtualMachineBulkAddInterfaceView(generic.BulkComponentCreateView):
  476. parent_model = VirtualMachine
  477. parent_field = 'virtual_machine'
  478. form = forms.VMInterfaceBulkCreateForm
  479. queryset = VMInterface.objects.all()
  480. model_form = forms.VMInterfaceForm
  481. filterset = filtersets.VirtualMachineFilterSet
  482. table = tables.VirtualMachineTable
  483. default_return_url = 'virtualization:virtualmachine_list'
  484. def get_required_permission(self):
  485. return 'virtualization.add_vminterface'
  486. class VirtualMachineBulkAddVirtualDiskView(generic.BulkComponentCreateView):
  487. parent_model = VirtualMachine
  488. parent_field = 'virtual_machine'
  489. form = forms.VirtualDiskBulkCreateForm
  490. queryset = VirtualDisk.objects.all()
  491. model_form = forms.VirtualDiskForm
  492. filterset = filtersets.VirtualMachineFilterSet
  493. table = tables.VirtualMachineTable
  494. default_return_url = 'virtualization:virtualmachine_list'
  495. def get_required_permission(self):
  496. return 'virtualization.add_virtualdisk'