views.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  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. filter = filters.ClusterFilter
  118. table = tables.ClusterTable
  119. default_return_url = 'virtualization:cluster_list'
  120. class ClusterAddDevicesView(PermissionRequiredMixin, View):
  121. permission_required = 'virtualization.change_cluster'
  122. form = forms.ClusterAddDevicesForm
  123. template_name = 'virtualization/cluster_add_devices.html'
  124. def get(self, request, pk):
  125. cluster = get_object_or_404(Cluster, pk=pk)
  126. form = self.form(cluster)
  127. return render(request, self.template_name, {
  128. 'cluster': cluster,
  129. 'form': form,
  130. 'return_url': reverse('virtualization:cluster', kwargs={'pk': pk}),
  131. })
  132. def post(self, request, pk):
  133. cluster = get_object_or_404(Cluster, pk=pk)
  134. form = self.form(cluster, request.POST)
  135. if form.is_valid():
  136. # Assign the selected Devices to the Cluster
  137. devices = form.cleaned_data['devices']
  138. Device.objects.filter(pk__in=devices).update(cluster=cluster)
  139. messages.success(request, "Added {} devices to cluster {}".format(
  140. len(devices), cluster
  141. ))
  142. return redirect(cluster.get_absolute_url())
  143. return render(request, self.template_name, {
  144. 'cluser': cluster,
  145. 'form': form,
  146. 'return_url': cluster.get_absolute_url(),
  147. })
  148. class ClusterRemoveDevicesView(PermissionRequiredMixin, View):
  149. permission_required = 'virtualization.change_cluster'
  150. form = forms.ClusterRemoveDevicesForm
  151. template_name = 'utilities/obj_bulk_remove.html'
  152. def post(self, request, pk):
  153. cluster = get_object_or_404(Cluster, pk=pk)
  154. if '_confirm' in request.POST:
  155. form = self.form(request.POST)
  156. if form.is_valid():
  157. # Remove the selected Devices from the Cluster
  158. devices = form.cleaned_data['pk']
  159. Device.objects.filter(pk__in=devices).update(cluster=None)
  160. messages.success(request, "Removed {} devices from cluster {}".format(
  161. len(devices), cluster
  162. ))
  163. return redirect(cluster.get_absolute_url())
  164. else:
  165. form = self.form(initial={'pk': request.POST.getlist('pk')})
  166. selected_objects = Device.objects.filter(pk__in=form.initial['pk'])
  167. device_table = DeviceTable(list(selected_objects), orderable=False)
  168. return render(request, self.template_name, {
  169. 'form': form,
  170. 'parent_obj': cluster,
  171. 'table': device_table,
  172. 'obj_type_plural': 'devices',
  173. 'return_url': cluster.get_absolute_url(),
  174. })
  175. #
  176. # Virtual machines
  177. #
  178. class VirtualMachineListView(ObjectListView):
  179. queryset = VirtualMachine.objects.select_related('cluster', 'tenant', 'primary_ip4', 'primary_ip6')
  180. filter = filters.VirtualMachineFilter
  181. filter_form = forms.VirtualMachineFilterForm
  182. table = tables.VirtualMachineDetailTable
  183. template_name = 'virtualization/virtualmachine_list.html'
  184. class VirtualMachineView(View):
  185. def get(self, request, pk):
  186. vm = get_object_or_404(VirtualMachine.objects.select_related('tenant__group'), pk=pk)
  187. interfaces = Interface.objects.filter(virtual_machine=vm)
  188. services = Service.objects.filter(virtual_machine=vm)
  189. return render(request, 'virtualization/virtualmachine.html', {
  190. 'vm': vm,
  191. 'interfaces': interfaces,
  192. 'services': services,
  193. })
  194. class VirtualMachineCreateView(PermissionRequiredMixin, ObjectEditView):
  195. permission_required = 'virtualization.add_virtualmachine'
  196. model = VirtualMachine
  197. model_form = forms.VirtualMachineForm
  198. template_name = 'virtualization/virtualmachine_edit.html'
  199. default_return_url = 'virtualization:virtualmachine_list'
  200. class VirtualMachineEditView(VirtualMachineCreateView):
  201. permission_required = 'virtualization.change_virtualmachine'
  202. class VirtualMachineDeleteView(PermissionRequiredMixin, ObjectDeleteView):
  203. permission_required = 'virtualization.delete_virtualmachine'
  204. model = VirtualMachine
  205. default_return_url = 'virtualization:virtualmachine_list'
  206. class VirtualMachineBulkImportView(PermissionRequiredMixin, BulkImportView):
  207. permission_required = 'virtualization.add_virtualmachine'
  208. model_form = forms.VirtualMachineCSVForm
  209. table = tables.VirtualMachineTable
  210. default_return_url = 'virtualization:virtualmachine_list'
  211. class VirtualMachineBulkEditView(PermissionRequiredMixin, BulkEditView):
  212. permission_required = 'virtualization.change_virtualmachine'
  213. cls = VirtualMachine
  214. queryset = VirtualMachine.objects.select_related('cluster', 'tenant')
  215. filter = filters.VirtualMachineFilter
  216. table = tables.VirtualMachineTable
  217. form = forms.VirtualMachineBulkEditForm
  218. default_return_url = 'virtualization:virtualmachine_list'
  219. class VirtualMachineBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
  220. permission_required = 'virtualization.delete_virtualmachine'
  221. cls = VirtualMachine
  222. queryset = VirtualMachine.objects.select_related('cluster', 'tenant')
  223. filter = filters.VirtualMachineFilter
  224. table = tables.VirtualMachineTable
  225. default_return_url = 'virtualization:virtualmachine_list'
  226. #
  227. # VM interfaces
  228. #
  229. class InterfaceCreateView(PermissionRequiredMixin, ComponentCreateView):
  230. permission_required = 'dcim.add_interface'
  231. parent_model = VirtualMachine
  232. parent_field = 'virtual_machine'
  233. model = Interface
  234. form = forms.InterfaceCreateForm
  235. model_form = forms.InterfaceForm
  236. template_name = 'virtualization/virtualmachine_component_add.html'
  237. class InterfaceEditView(PermissionRequiredMixin, ObjectEditView):
  238. permission_required = 'dcim.change_interface'
  239. model = Interface
  240. model_form = forms.InterfaceForm
  241. template_name = 'virtualization/interface_edit.html'
  242. class InterfaceDeleteView(PermissionRequiredMixin, ObjectDeleteView):
  243. permission_required = 'dcim.delete_interface'
  244. model = Interface
  245. class InterfaceBulkEditView(PermissionRequiredMixin, BulkEditView):
  246. permission_required = 'dcim.change_interface'
  247. cls = Interface
  248. parent_cls = VirtualMachine
  249. table = tables.InterfaceTable
  250. form = forms.InterfaceBulkEditForm
  251. class InterfaceBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
  252. permission_required = 'dcim.delete_interface'
  253. cls = Interface
  254. parent_cls = VirtualMachine
  255. table = tables.InterfaceTable
  256. #
  257. # Bulk Device component creation
  258. #
  259. class VirtualMachineBulkAddInterfaceView(PermissionRequiredMixin, BulkComponentCreateView):
  260. permission_required = 'dcim.add_interface'
  261. parent_model = VirtualMachine
  262. parent_field = 'virtual_machine'
  263. form = forms.VirtualMachineBulkAddInterfaceForm
  264. model = Interface
  265. model_form = forms.InterfaceForm
  266. table = tables.VirtualMachineTable
  267. default_return_url = 'virtualization:virtualmachine_list'