views.py 22 KB

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