views.py 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681
  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 tenancy.views import ObjectContactsView
  18. from utilities.query import count_related
  19. from utilities.query_functions import CollateAsChar
  20. from utilities.views import GetRelatedModelsMixin, ViewTab, register_model_view
  21. from . import filtersets, forms, tables
  22. from .models import *
  23. #
  24. # Cluster types
  25. #
  26. @register_model_view(ClusterType, 'list', path='', detail=False)
  27. class ClusterTypeListView(generic.ObjectListView):
  28. queryset = ClusterType.objects.annotate(
  29. cluster_count=count_related(Cluster, 'type')
  30. )
  31. filterset = filtersets.ClusterTypeFilterSet
  32. filterset_form = forms.ClusterTypeFilterForm
  33. table = tables.ClusterTypeTable
  34. @register_model_view(ClusterType)
  35. class ClusterTypeView(GetRelatedModelsMixin, generic.ObjectView):
  36. queryset = ClusterType.objects.all()
  37. def get_extra_context(self, request, instance):
  38. return {
  39. 'related_models': self.get_related_models(request, instance),
  40. }
  41. @register_model_view(ClusterType, 'add', detail=False)
  42. @register_model_view(ClusterType, 'edit')
  43. class ClusterTypeEditView(generic.ObjectEditView):
  44. queryset = ClusterType.objects.all()
  45. form = forms.ClusterTypeForm
  46. @register_model_view(ClusterType, 'delete')
  47. class ClusterTypeDeleteView(generic.ObjectDeleteView):
  48. queryset = ClusterType.objects.all()
  49. @register_model_view(ClusterType, 'bulk_import', detail=False)
  50. class ClusterTypeBulkImportView(generic.BulkImportView):
  51. queryset = ClusterType.objects.all()
  52. model_form = forms.ClusterTypeImportForm
  53. @register_model_view(ClusterType, 'bulk_edit', path='edit', detail=False)
  54. class ClusterTypeBulkEditView(generic.BulkEditView):
  55. queryset = ClusterType.objects.annotate(
  56. cluster_count=count_related(Cluster, 'type')
  57. )
  58. filterset = filtersets.ClusterTypeFilterSet
  59. table = tables.ClusterTypeTable
  60. form = forms.ClusterTypeBulkEditForm
  61. @register_model_view(ClusterType, 'bulk_delete', path='delete', detail=False)
  62. class ClusterTypeBulkDeleteView(generic.BulkDeleteView):
  63. queryset = ClusterType.objects.annotate(
  64. cluster_count=count_related(Cluster, 'type')
  65. )
  66. filterset = filtersets.ClusterTypeFilterSet
  67. table = tables.ClusterTypeTable
  68. #
  69. # Cluster groups
  70. #
  71. @register_model_view(ClusterGroup, 'list', path='', detail=False)
  72. class ClusterGroupListView(generic.ObjectListView):
  73. queryset = ClusterGroup.objects.annotate(
  74. cluster_count=count_related(Cluster, 'group')
  75. )
  76. filterset = filtersets.ClusterGroupFilterSet
  77. filterset_form = forms.ClusterGroupFilterForm
  78. table = tables.ClusterGroupTable
  79. @register_model_view(ClusterGroup)
  80. class ClusterGroupView(GetRelatedModelsMixin, generic.ObjectView):
  81. queryset = ClusterGroup.objects.all()
  82. def get_extra_context(self, request, instance):
  83. return {
  84. 'related_models': self.get_related_models(request, instance),
  85. }
  86. @register_model_view(ClusterGroup, 'add', detail=False)
  87. @register_model_view(ClusterGroup, 'edit')
  88. class ClusterGroupEditView(generic.ObjectEditView):
  89. queryset = ClusterGroup.objects.all()
  90. form = forms.ClusterGroupForm
  91. @register_model_view(ClusterGroup, 'delete')
  92. class ClusterGroupDeleteView(generic.ObjectDeleteView):
  93. queryset = ClusterGroup.objects.all()
  94. @register_model_view(ClusterGroup, 'bulk_import', detail=False)
  95. class ClusterGroupBulkImportView(generic.BulkImportView):
  96. queryset = ClusterGroup.objects.annotate(
  97. cluster_count=count_related(Cluster, 'group')
  98. )
  99. model_form = forms.ClusterGroupImportForm
  100. @register_model_view(ClusterGroup, 'bulk_edit', path='edit', detail=False)
  101. class ClusterGroupBulkEditView(generic.BulkEditView):
  102. queryset = ClusterGroup.objects.annotate(
  103. cluster_count=count_related(Cluster, 'group')
  104. )
  105. filterset = filtersets.ClusterGroupFilterSet
  106. table = tables.ClusterGroupTable
  107. form = forms.ClusterGroupBulkEditForm
  108. @register_model_view(ClusterGroup, 'bulk_delete', path='delete', detail=False)
  109. class ClusterGroupBulkDeleteView(generic.BulkDeleteView):
  110. queryset = ClusterGroup.objects.annotate(
  111. cluster_count=count_related(Cluster, 'group')
  112. )
  113. filterset = filtersets.ClusterGroupFilterSet
  114. table = tables.ClusterGroupTable
  115. @register_model_view(ClusterGroup, 'contacts')
  116. class ClusterGroupContactsView(ObjectContactsView):
  117. queryset = ClusterGroup.objects.all()
  118. #
  119. # Clusters
  120. #
  121. @register_model_view(Cluster, 'list', path='', detail=False)
  122. class ClusterListView(generic.ObjectListView):
  123. permission_required = 'virtualization.view_cluster'
  124. queryset = Cluster.objects.annotate(
  125. device_count=count_related(Device, 'cluster'),
  126. vm_count=count_related(VirtualMachine, 'cluster')
  127. )
  128. table = tables.ClusterTable
  129. filterset = filtersets.ClusterFilterSet
  130. filterset_form = forms.ClusterFilterForm
  131. @register_model_view(Cluster)
  132. class ClusterView(GetRelatedModelsMixin, generic.ObjectView):
  133. queryset = Cluster.objects.all()
  134. def get_extra_context(self, request, instance):
  135. return {
  136. **instance.virtual_machines.aggregate(
  137. vcpus_sum=Sum('vcpus'),
  138. memory_sum=Sum('memory'),
  139. disk_sum=Sum('disk')
  140. ),
  141. 'related_models': self.get_related_models(
  142. request,
  143. instance,
  144. omit=(),
  145. extra=(
  146. (VLANGroup.objects.restrict(request.user, 'view').filter(
  147. scope_type=ContentType.objects.get_for_model(Cluster),
  148. scope_id=instance.pk
  149. ), 'cluster'),
  150. )
  151. ),
  152. }
  153. @register_model_view(Cluster, 'virtualmachines', path='virtual-machines')
  154. class ClusterVirtualMachinesView(generic.ObjectChildrenView):
  155. queryset = Cluster.objects.all()
  156. child_model = VirtualMachine
  157. table = tables.VirtualMachineTable
  158. filterset = filtersets.VirtualMachineFilterSet
  159. filterset_form = forms.VirtualMachineFilterForm
  160. tab = ViewTab(
  161. label=_('Virtual Machines'),
  162. badge=lambda obj: obj.virtual_machines.count(),
  163. permission='virtualization.view_virtualmachine',
  164. weight=500
  165. )
  166. def get_children(self, request, parent):
  167. return VirtualMachine.objects.restrict(request.user, 'view').filter(cluster=parent)
  168. @register_model_view(Cluster, 'devices')
  169. class ClusterDevicesView(generic.ObjectChildrenView):
  170. queryset = Cluster.objects.all()
  171. child_model = Device
  172. table = DeviceTable
  173. filterset = DeviceFilterSet
  174. filterset_form = DeviceFilterForm
  175. template_name = 'virtualization/cluster/devices.html'
  176. actions = {
  177. 'add': {'add'},
  178. 'export': {'view'},
  179. 'bulk_import': {'add'},
  180. 'bulk_edit': {'change'},
  181. 'bulk_remove_devices': {'change'},
  182. }
  183. tab = ViewTab(
  184. label=_('Devices'),
  185. badge=lambda obj: obj.devices.count(),
  186. permission='virtualization.view_virtualmachine',
  187. weight=600
  188. )
  189. def get_children(self, request, parent):
  190. return Device.objects.restrict(request.user, 'view').filter(cluster=parent)
  191. @register_model_view(Cluster, 'add', detail=False)
  192. @register_model_view(Cluster, 'edit')
  193. class ClusterEditView(generic.ObjectEditView):
  194. queryset = Cluster.objects.all()
  195. form = forms.ClusterForm
  196. @register_model_view(Cluster, 'delete')
  197. class ClusterDeleteView(generic.ObjectDeleteView):
  198. queryset = Cluster.objects.all()
  199. @register_model_view(Cluster, 'bulk_import', detail=False)
  200. class ClusterBulkImportView(generic.BulkImportView):
  201. queryset = Cluster.objects.all()
  202. model_form = forms.ClusterImportForm
  203. @register_model_view(Cluster, 'bulk_edit', path='edit', detail=False)
  204. class ClusterBulkEditView(generic.BulkEditView):
  205. queryset = Cluster.objects.all()
  206. filterset = filtersets.ClusterFilterSet
  207. table = tables.ClusterTable
  208. form = forms.ClusterBulkEditForm
  209. @register_model_view(Cluster, 'bulk_delete', path='delete', detail=False)
  210. class ClusterBulkDeleteView(generic.BulkDeleteView):
  211. queryset = Cluster.objects.all()
  212. filterset = filtersets.ClusterFilterSet
  213. table = tables.ClusterTable
  214. @register_model_view(Cluster, 'add_devices', path='devices/add')
  215. class ClusterAddDevicesView(generic.ObjectEditView):
  216. queryset = Cluster.objects.all()
  217. form = forms.ClusterAddDevicesForm
  218. template_name = 'virtualization/cluster_add_devices.html'
  219. def get(self, request, pk):
  220. cluster = get_object_or_404(self.queryset, pk=pk)
  221. form = self.form(cluster, initial=request.GET)
  222. return render(request, self.template_name, {
  223. 'cluster': cluster,
  224. 'form': form,
  225. 'return_url': reverse('virtualization:cluster', kwargs={'pk': pk}),
  226. })
  227. def post(self, request, pk):
  228. cluster = get_object_or_404(self.queryset, pk=pk)
  229. form = self.form(cluster, request.POST)
  230. if form.is_valid():
  231. device_pks = form.cleaned_data['devices']
  232. with transaction.atomic():
  233. # Assign the selected Devices to the Cluster
  234. for device in Device.objects.filter(pk__in=device_pks):
  235. device.cluster = cluster
  236. device.save()
  237. messages.success(request, _("Added {count} devices to cluster {cluster}").format(
  238. count=len(device_pks),
  239. cluster=cluster
  240. ))
  241. return redirect(cluster.get_absolute_url())
  242. return render(request, self.template_name, {
  243. 'cluster': cluster,
  244. 'form': form,
  245. 'return_url': cluster.get_absolute_url(),
  246. })
  247. @register_model_view(Cluster, 'remove_devices', path='devices/remove')
  248. class ClusterRemoveDevicesView(generic.ObjectEditView):
  249. queryset = Cluster.objects.all()
  250. form = forms.ClusterRemoveDevicesForm
  251. template_name = 'generic/bulk_remove.html'
  252. def post(self, request, pk):
  253. cluster = get_object_or_404(self.queryset, pk=pk)
  254. if '_confirm' in request.POST:
  255. form = self.form(request.POST)
  256. if form.is_valid():
  257. device_pks = form.cleaned_data['pk']
  258. with transaction.atomic():
  259. # Remove the selected Devices from the Cluster
  260. for device in Device.objects.filter(pk__in=device_pks):
  261. device.cluster = None
  262. device.save()
  263. messages.success(request, _("Removed {count} devices from cluster {cluster}").format(
  264. count=len(device_pks),
  265. cluster=cluster
  266. ))
  267. return redirect(cluster.get_absolute_url())
  268. else:
  269. form = self.form(initial={'pk': request.POST.getlist('pk')})
  270. selected_objects = Device.objects.filter(pk__in=form.initial['pk'])
  271. device_table = DeviceTable(list(selected_objects), orderable=False)
  272. return render(request, self.template_name, {
  273. 'form': form,
  274. 'parent_obj': cluster,
  275. 'table': device_table,
  276. 'obj_type_plural': 'devices',
  277. 'return_url': cluster.get_absolute_url(),
  278. })
  279. @register_model_view(Cluster, 'contacts')
  280. class ClusterContactsView(ObjectContactsView):
  281. queryset = Cluster.objects.all()
  282. #
  283. # Virtual machines
  284. #
  285. @register_model_view(VirtualMachine, 'list', path='', detail=False)
  286. class VirtualMachineListView(generic.ObjectListView):
  287. queryset = VirtualMachine.objects.prefetch_related('primary_ip4', 'primary_ip6')
  288. filterset = filtersets.VirtualMachineFilterSet
  289. filterset_form = forms.VirtualMachineFilterForm
  290. table = tables.VirtualMachineTable
  291. template_name = 'virtualization/virtualmachine_list.html'
  292. @register_model_view(VirtualMachine)
  293. class VirtualMachineView(generic.ObjectView):
  294. queryset = VirtualMachine.objects.all()
  295. @register_model_view(VirtualMachine, 'interfaces')
  296. class VirtualMachineInterfacesView(generic.ObjectChildrenView):
  297. queryset = VirtualMachine.objects.all()
  298. child_model = VMInterface
  299. table = tables.VirtualMachineVMInterfaceTable
  300. filterset = filtersets.VMInterfaceFilterSet
  301. filterset_form = forms.VMInterfaceFilterForm
  302. template_name = 'virtualization/virtualmachine/interfaces.html'
  303. actions = {
  304. **DEFAULT_ACTION_PERMISSIONS,
  305. 'bulk_rename': {'change'},
  306. }
  307. tab = ViewTab(
  308. label=_('Interfaces'),
  309. badge=lambda obj: obj.interface_count,
  310. permission='virtualization.view_vminterface',
  311. weight=500
  312. )
  313. def get_children(self, request, parent):
  314. return parent.interfaces.restrict(request.user, 'view').prefetch_related(
  315. Prefetch('ip_addresses', queryset=IPAddress.objects.restrict(request.user)),
  316. 'tags',
  317. )
  318. @register_model_view(VirtualMachine, 'disks')
  319. class VirtualMachineVirtualDisksView(generic.ObjectChildrenView):
  320. queryset = VirtualMachine.objects.all()
  321. child_model = VirtualDisk
  322. table = tables.VirtualMachineVirtualDiskTable
  323. filterset = filtersets.VirtualDiskFilterSet
  324. filterset_form = forms.VirtualDiskFilterForm
  325. template_name = 'virtualization/virtualmachine/virtual_disks.html'
  326. tab = ViewTab(
  327. label=_('Virtual Disks'),
  328. badge=lambda obj: obj.virtual_disk_count,
  329. permission='virtualization.view_virtualdisk',
  330. weight=500
  331. )
  332. actions = {
  333. **DEFAULT_ACTION_PERMISSIONS,
  334. 'bulk_rename': {'change'},
  335. }
  336. def get_children(self, request, parent):
  337. return parent.virtualdisks.restrict(request.user, 'view').prefetch_related('tags')
  338. @register_model_view(VirtualMachine, 'configcontext', path='config-context')
  339. class VirtualMachineConfigContextView(ObjectConfigContextView):
  340. queryset = VirtualMachine.objects.annotate_config_context_data()
  341. base_template = 'virtualization/virtualmachine.html'
  342. tab = ViewTab(
  343. label=_('Config Context'),
  344. weight=2000
  345. )
  346. @register_model_view(VirtualMachine, 'render-config')
  347. class VirtualMachineRenderConfigView(ObjectRenderConfigView):
  348. queryset = VirtualMachine.objects.all()
  349. base_template = 'virtualization/virtualmachine/base.html'
  350. tab = ViewTab(
  351. label=_('Render Config'),
  352. weight=2100,
  353. )
  354. @register_model_view(VirtualMachine, 'add', detail=False)
  355. @register_model_view(VirtualMachine, 'edit')
  356. class VirtualMachineEditView(generic.ObjectEditView):
  357. queryset = VirtualMachine.objects.all()
  358. form = forms.VirtualMachineForm
  359. @register_model_view(VirtualMachine, 'delete')
  360. class VirtualMachineDeleteView(generic.ObjectDeleteView):
  361. queryset = VirtualMachine.objects.all()
  362. @register_model_view(VirtualMachine, 'bulk_import', detail=False)
  363. class VirtualMachineBulkImportView(generic.BulkImportView):
  364. queryset = VirtualMachine.objects.all()
  365. model_form = forms.VirtualMachineImportForm
  366. @register_model_view(VirtualMachine, 'bulk_edit', path='edit', detail=False)
  367. class VirtualMachineBulkEditView(generic.BulkEditView):
  368. queryset = VirtualMachine.objects.prefetch_related('primary_ip4', 'primary_ip6')
  369. filterset = filtersets.VirtualMachineFilterSet
  370. table = tables.VirtualMachineTable
  371. form = forms.VirtualMachineBulkEditForm
  372. @register_model_view(VirtualMachine, 'bulk_delete', path='delete', detail=False)
  373. class VirtualMachineBulkDeleteView(generic.BulkDeleteView):
  374. queryset = VirtualMachine.objects.prefetch_related('primary_ip4', 'primary_ip6')
  375. filterset = filtersets.VirtualMachineFilterSet
  376. table = tables.VirtualMachineTable
  377. @register_model_view(VirtualMachine, 'contacts')
  378. class VirtualMachineContactsView(ObjectContactsView):
  379. queryset = VirtualMachine.objects.all()
  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'