views.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. from __future__ import unicode_literals
  2. from django.contrib import messages
  3. from django.contrib.auth.mixins import PermissionRequiredMixin
  4. from django.db.models import Count
  5. from django.shortcuts import get_object_or_404, redirect, render
  6. from django.urls import reverse
  7. from django.views.generic import View
  8. from dcim.models import Device, Interface
  9. from dcim.tables import DeviceTable
  10. from ipam.models import Service
  11. from utilities.views import (
  12. BulkComponentCreateView, BulkDeleteView, BulkEditView, BulkImportView, ComponentCreateView, ObjectDeleteView,
  13. ObjectEditView, ObjectListView,
  14. )
  15. from . import filters, forms, tables
  16. from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine
  17. #
  18. # Cluster types
  19. #
  20. class ClusterTypeListView(ObjectListView):
  21. queryset = ClusterType.objects.annotate(cluster_count=Count('clusters'))
  22. table = tables.ClusterTypeTable
  23. template_name = 'virtualization/clustertype_list.html'
  24. class ClusterTypeCreateView(PermissionRequiredMixin, ObjectEditView):
  25. permission_required = 'virtualization.add_clustertype'
  26. model = ClusterType
  27. model_form = forms.ClusterTypeForm
  28. def get_return_url(self, request, obj):
  29. return reverse('virtualization:clustertype_list')
  30. class ClusterTypeEditView(ClusterTypeCreateView):
  31. permission_required = 'virtualization.change_clustertype'
  32. class ClusterTypeBulkImportView(PermissionRequiredMixin, BulkImportView):
  33. permission_required = 'virtualization.add_clustertype'
  34. model_form = forms.ClusterTypeCSVForm
  35. table = tables.ClusterTypeTable
  36. default_return_url = 'virtualization:clustertype_list'
  37. class ClusterTypeBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
  38. permission_required = 'virtualization.delete_clustertype'
  39. cls = ClusterType
  40. queryset = ClusterType.objects.annotate(cluster_count=Count('clusters'))
  41. table = tables.ClusterTypeTable
  42. default_return_url = 'virtualization:clustertype_list'
  43. #
  44. # Cluster groups
  45. #
  46. class ClusterGroupListView(ObjectListView):
  47. queryset = ClusterGroup.objects.annotate(cluster_count=Count('clusters'))
  48. table = tables.ClusterGroupTable
  49. template_name = 'virtualization/clustergroup_list.html'
  50. class ClusterGroupCreateView(PermissionRequiredMixin, ObjectEditView):
  51. permission_required = 'virtualization.add_clustergroup'
  52. model = ClusterGroup
  53. model_form = forms.ClusterGroupForm
  54. def get_return_url(self, request, obj):
  55. return reverse('virtualization:clustergroup_list')
  56. class ClusterGroupEditView(ClusterGroupCreateView):
  57. permission_required = 'virtualization.change_clustergroup'
  58. class ClusterGroupBulkImportView(PermissionRequiredMixin, BulkImportView):
  59. permission_required = 'virtualization.add_clustergroup'
  60. model_form = forms.ClusterGroupCSVForm
  61. table = tables.ClusterGroupTable
  62. default_return_url = 'virtualization:clustergroup_list'
  63. class ClusterGroupBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
  64. permission_required = 'virtualization.delete_clustergroup'
  65. cls = ClusterGroup
  66. queryset = ClusterGroup.objects.annotate(cluster_count=Count('clusters'))
  67. table = tables.ClusterGroupTable
  68. default_return_url = 'virtualization:clustergroup_list'
  69. #
  70. # Clusters
  71. #
  72. class ClusterListView(ObjectListView):
  73. queryset = Cluster.objects.select_related('type', 'group')
  74. table = tables.ClusterTable
  75. filter = filters.ClusterFilter
  76. filter_form = forms.ClusterFilterForm
  77. template_name = 'virtualization/cluster_list.html'
  78. class ClusterView(View):
  79. def get(self, request, pk):
  80. cluster = get_object_or_404(Cluster, pk=pk)
  81. devices = Device.objects.filter(cluster=cluster).select_related(
  82. 'site', 'rack', 'tenant', 'device_type__manufacturer'
  83. )
  84. device_table = DeviceTable(list(devices), orderable=False)
  85. if request.user.has_perm('virtualization:change_cluster'):
  86. device_table.columns.show('pk')
  87. return render(request, 'virtualization/cluster.html', {
  88. 'cluster': cluster,
  89. 'device_table': device_table,
  90. })
  91. class ClusterCreateView(PermissionRequiredMixin, ObjectEditView):
  92. permission_required = 'virtualization.add_cluster'
  93. model = Cluster
  94. model_form = forms.ClusterForm
  95. class ClusterEditView(ClusterCreateView):
  96. permission_required = 'virtualization.change_cluster'
  97. class ClusterDeleteView(PermissionRequiredMixin, ObjectDeleteView):
  98. permission_required = 'virtualization.delete_cluster'
  99. model = Cluster
  100. default_return_url = 'virtualization:cluster_list'
  101. class ClusterBulkImportView(PermissionRequiredMixin, BulkImportView):
  102. permission_required = 'virtualization.add_cluster'
  103. model_form = forms.ClusterCSVForm
  104. table = tables.ClusterTable
  105. default_return_url = 'virtualization:cluster_list'
  106. class ClusterBulkEditView(PermissionRequiredMixin, BulkEditView):
  107. permission_required = 'virtualization.change_cluster'
  108. cls = Cluster
  109. filter = filters.ClusterFilter
  110. table = tables.ClusterTable
  111. form = forms.ClusterBulkEditForm
  112. default_return_url = 'virtualization:cluster_list'
  113. class ClusterBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
  114. permission_required = 'virtualization.delete_cluster'
  115. cls = Cluster
  116. queryset = Cluster.objects.all()
  117. table = tables.ClusterTable
  118. default_return_url = 'virtualization:cluster_list'
  119. class ClusterAddDevicesView(PermissionRequiredMixin, View):
  120. permission_required = 'virtualization.change_cluster'
  121. form = forms.ClusterAddDevicesForm
  122. template_name = 'virtualization/cluster_add_devices.html'
  123. def get(self, request, pk):
  124. cluster = get_object_or_404(Cluster, pk=pk)
  125. form = self.form(cluster)
  126. return render(request, self.template_name, {
  127. 'cluster': cluster,
  128. 'form': form,
  129. 'return_url': reverse('virtualization:cluster', kwargs={'pk': pk}),
  130. })
  131. def post(self, request, pk):
  132. cluster = get_object_or_404(Cluster, pk=pk)
  133. form = self.form(cluster, request.POST)
  134. if form.is_valid():
  135. # Assign the selected Devices to the Cluster
  136. devices = form.cleaned_data['devices']
  137. Device.objects.filter(pk__in=devices).update(cluster=cluster)
  138. messages.success(request, "Added {} devices to cluster {}".format(
  139. len(devices), cluster
  140. ))
  141. return redirect(cluster.get_absolute_url())
  142. return render(request, self.template_name, {
  143. 'cluser': cluster,
  144. 'form': form,
  145. 'return_url': cluster.get_absolute_url(),
  146. })
  147. class ClusterRemoveDevicesView(PermissionRequiredMixin, View):
  148. permission_required = 'virtualization.change_cluster'
  149. form = forms.ClusterRemoveDevicesForm
  150. template_name = 'utilities/obj_bulk_remove.html'
  151. def post(self, request, pk):
  152. cluster = get_object_or_404(Cluster, pk=pk)
  153. if '_confirm' in request.POST:
  154. form = self.form(request.POST)
  155. if form.is_valid():
  156. # Remove the selected Devices from the Cluster
  157. devices = form.cleaned_data['pk']
  158. Device.objects.filter(pk__in=devices).update(cluster=None)
  159. messages.success(request, "Removed {} devices from cluster {}".format(
  160. len(devices), cluster
  161. ))
  162. return redirect(cluster.get_absolute_url())
  163. else:
  164. form = self.form(initial={'pk': request.POST.getlist('pk')})
  165. selected_objects = Device.objects.filter(pk__in=form.initial['pk'])
  166. device_table = DeviceTable(list(selected_objects), orderable=False)
  167. return render(request, self.template_name, {
  168. 'form': form,
  169. 'parent_obj': cluster,
  170. 'table': device_table,
  171. 'obj_type_plural': 'devices',
  172. 'return_url': cluster.get_absolute_url(),
  173. })
  174. #
  175. # Virtual machines
  176. #
  177. class VirtualMachineListView(ObjectListView):
  178. queryset = VirtualMachine.objects.select_related('cluster', 'tenant', 'primary_ip4', 'primary_ip6')
  179. filter = filters.VirtualMachineFilter
  180. filter_form = forms.VirtualMachineFilterForm
  181. table = tables.VirtualMachineDetailTable
  182. template_name = 'virtualization/virtualmachine_list.html'
  183. class VirtualMachineView(View):
  184. def get(self, request, pk):
  185. vm = get_object_or_404(VirtualMachine.objects.select_related('tenant__group'), pk=pk)
  186. interfaces = Interface.objects.filter(virtual_machine=vm)
  187. services = Service.objects.filter(virtual_machine=vm)
  188. return render(request, 'virtualization/virtualmachine.html', {
  189. 'vm': vm,
  190. 'interfaces': interfaces,
  191. 'services': services,
  192. })
  193. class VirtualMachineCreateView(PermissionRequiredMixin, ObjectEditView):
  194. permission_required = 'virtualization.add_virtualmachine'
  195. model = VirtualMachine
  196. model_form = forms.VirtualMachineForm
  197. template_name = 'virtualization/virtualmachine_edit.html'
  198. default_return_url = 'virtualization:virtualmachine_list'
  199. class VirtualMachineEditView(VirtualMachineCreateView):
  200. permission_required = 'virtualization.change_virtualmachine'
  201. class VirtualMachineDeleteView(PermissionRequiredMixin, ObjectDeleteView):
  202. permission_required = 'virtualization.delete_virtualmachine'
  203. model = VirtualMachine
  204. default_return_url = 'virtualization:virtualmachine_list'
  205. class VirtualMachineBulkImportView(PermissionRequiredMixin, BulkImportView):
  206. permission_required = 'virtualization.add_virtualmachine'
  207. model_form = forms.VirtualMachineCSVForm
  208. table = tables.VirtualMachineTable
  209. default_return_url = 'virtualization:virtualmachine_list'
  210. class VirtualMachineBulkEditView(PermissionRequiredMixin, BulkEditView):
  211. permission_required = 'virtualization.change_virtualmachine'
  212. cls = VirtualMachine
  213. queryset = VirtualMachine.objects.select_related('cluster', 'tenant')
  214. filter = filters.VirtualMachineFilter
  215. table = tables.VirtualMachineTable
  216. form = forms.VirtualMachineBulkEditForm
  217. default_return_url = 'virtualization:virtualmachine_list'
  218. class VirtualMachineBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
  219. permission_required = 'virtualization.delete_virtualmachine'
  220. cls = VirtualMachine
  221. queryset = VirtualMachine.objects.select_related('cluster', 'tenant')
  222. filter = filters.VirtualMachineFilter
  223. table = tables.VirtualMachineTable
  224. default_return_url = 'virtualization:virtualmachine_list'
  225. #
  226. # VM interfaces
  227. #
  228. class InterfaceCreateView(PermissionRequiredMixin, ComponentCreateView):
  229. permission_required = 'dcim.add_interface'
  230. parent_model = VirtualMachine
  231. parent_field = 'virtual_machine'
  232. model = Interface
  233. form = forms.InterfaceCreateForm
  234. model_form = forms.InterfaceForm
  235. template_name = 'virtualization/virtualmachine_component_add.html'
  236. class InterfaceEditView(PermissionRequiredMixin, ObjectEditView):
  237. permission_required = 'dcim.change_interface'
  238. model = Interface
  239. model_form = forms.InterfaceForm
  240. class InterfaceDeleteView(PermissionRequiredMixin, ObjectDeleteView):
  241. permission_required = 'dcim.delete_interface'
  242. model = Interface
  243. class InterfaceBulkEditView(PermissionRequiredMixin, BulkEditView):
  244. permission_required = 'dcim.change_interface'
  245. cls = Interface
  246. parent_cls = VirtualMachine
  247. table = tables.InterfaceTable
  248. form = forms.InterfaceBulkEditForm
  249. class InterfaceBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
  250. permission_required = 'dcim.delete_interface'
  251. cls = Interface
  252. parent_cls = VirtualMachine
  253. table = tables.InterfaceTable
  254. #
  255. # Bulk Device component creation
  256. #
  257. class VirtualMachineBulkAddInterfaceView(PermissionRequiredMixin, BulkComponentCreateView):
  258. permission_required = 'dcim.add_interface'
  259. parent_model = VirtualMachine
  260. parent_field = 'virtual_machine'
  261. form = forms.VirtualMachineBulkAddInterfaceForm
  262. model = Interface
  263. model_form = forms.InterfaceForm
  264. table = tables.VirtualMachineTable
  265. default_return_url = 'virtualization:virtualmachine_list'