views.py 12 KB

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