views.py 22 KB

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