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 extras.views import ObjectConfigContextView
  11. from ipam.models import Service
  12. from utilities.views import (
  13. BulkComponentCreateView, BulkDeleteView, BulkEditView, BulkImportView, ComponentCreateView, ObjectDeleteView,
  14. ObjectEditView, ObjectListView,
  15. )
  16. from . import filters, forms, tables
  17. from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine
  18. #
  19. # Cluster types
  20. #
  21. class ClusterTypeListView(ObjectListView):
  22. queryset = ClusterType.objects.annotate(cluster_count=Count('clusters'))
  23. table = tables.ClusterTypeTable
  24. template_name = 'virtualization/clustertype_list.html'
  25. class ClusterTypeCreateView(PermissionRequiredMixin, ObjectEditView):
  26. permission_required = 'virtualization.add_clustertype'
  27. model = ClusterType
  28. model_form = forms.ClusterTypeForm
  29. default_return_url = '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. queryset = ClusterType.objects.annotate(cluster_count=Count('clusters'))
  40. table = tables.ClusterTypeTable
  41. default_return_url = 'virtualization:clustertype_list'
  42. #
  43. # Cluster groups
  44. #
  45. class ClusterGroupListView(ObjectListView):
  46. queryset = ClusterGroup.objects.annotate(cluster_count=Count('clusters'))
  47. table = tables.ClusterGroupTable
  48. template_name = 'virtualization/clustergroup_list.html'
  49. class ClusterGroupCreateView(PermissionRequiredMixin, ObjectEditView):
  50. permission_required = 'virtualization.add_clustergroup'
  51. model = ClusterGroup
  52. model_form = forms.ClusterGroupForm
  53. default_return_url = 'virtualization:clustergroup_list'
  54. class ClusterGroupEditView(ClusterGroupCreateView):
  55. permission_required = 'virtualization.change_clustergroup'
  56. class ClusterGroupBulkImportView(PermissionRequiredMixin, BulkImportView):
  57. permission_required = 'virtualization.add_clustergroup'
  58. model_form = forms.ClusterGroupCSVForm
  59. table = tables.ClusterGroupTable
  60. default_return_url = 'virtualization:clustergroup_list'
  61. class ClusterGroupBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
  62. permission_required = 'virtualization.delete_clustergroup'
  63. queryset = ClusterGroup.objects.annotate(cluster_count=Count('clusters'))
  64. table = tables.ClusterGroupTable
  65. default_return_url = 'virtualization:clustergroup_list'
  66. #
  67. # Clusters
  68. #
  69. class ClusterListView(ObjectListView):
  70. queryset = Cluster.objects.select_related('type', 'group', 'site')
  71. table = tables.ClusterTable
  72. filter = filters.ClusterFilter
  73. filter_form = forms.ClusterFilterForm
  74. template_name = 'virtualization/cluster_list.html'
  75. class ClusterView(View):
  76. def get(self, request, pk):
  77. cluster = get_object_or_404(Cluster, pk=pk)
  78. devices = Device.objects.filter(cluster=cluster).select_related(
  79. 'site', 'rack', 'tenant', 'device_type__manufacturer'
  80. )
  81. device_table = DeviceTable(list(devices), orderable=False)
  82. if request.user.has_perm('virtualization.change_cluster'):
  83. device_table.columns.show('pk')
  84. return render(request, 'virtualization/cluster.html', {
  85. 'cluster': cluster,
  86. 'device_table': device_table,
  87. })
  88. class ClusterCreateView(PermissionRequiredMixin, ObjectEditView):
  89. permission_required = 'virtualization.add_cluster'
  90. template_name = 'virtualization/cluster_edit.html'
  91. model = Cluster
  92. model_form = forms.ClusterForm
  93. class ClusterEditView(ClusterCreateView):
  94. permission_required = 'virtualization.change_cluster'
  95. class ClusterDeleteView(PermissionRequiredMixin, ObjectDeleteView):
  96. permission_required = 'virtualization.delete_cluster'
  97. model = Cluster
  98. default_return_url = 'virtualization:cluster_list'
  99. class ClusterBulkImportView(PermissionRequiredMixin, BulkImportView):
  100. permission_required = 'virtualization.add_cluster'
  101. model_form = forms.ClusterCSVForm
  102. table = tables.ClusterTable
  103. default_return_url = 'virtualization:cluster_list'
  104. class ClusterBulkEditView(PermissionRequiredMixin, BulkEditView):
  105. permission_required = 'virtualization.change_cluster'
  106. queryset = Cluster.objects.select_related('type', 'group', 'site')
  107. filter = filters.ClusterFilter
  108. table = tables.ClusterTable
  109. form = forms.ClusterBulkEditForm
  110. default_return_url = 'virtualization:cluster_list'
  111. class ClusterBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
  112. permission_required = 'virtualization.delete_cluster'
  113. queryset = Cluster.objects.select_related('type', 'group', 'site')
  114. filter = filters.ClusterFilter
  115. table = tables.ClusterTable
  116. default_return_url = 'virtualization:cluster_list'
  117. class ClusterAddDevicesView(PermissionRequiredMixin, View):
  118. permission_required = 'virtualization.change_cluster'
  119. form = forms.ClusterAddDevicesForm
  120. template_name = 'virtualization/cluster_add_devices.html'
  121. def get(self, request, pk):
  122. cluster = get_object_or_404(Cluster, pk=pk)
  123. form = self.form(cluster)
  124. return render(request, self.template_name, {
  125. 'cluster': cluster,
  126. 'form': form,
  127. 'return_url': reverse('virtualization:cluster', kwargs={'pk': pk}),
  128. })
  129. def post(self, request, pk):
  130. cluster = get_object_or_404(Cluster, pk=pk)
  131. form = self.form(cluster, request.POST)
  132. if form.is_valid():
  133. # Assign the selected Devices to the Cluster
  134. devices = form.cleaned_data['devices']
  135. Device.objects.filter(pk__in=devices).update(cluster=cluster)
  136. messages.success(request, "Added {} devices to cluster {}".format(
  137. len(devices), cluster
  138. ))
  139. return redirect(cluster.get_absolute_url())
  140. return render(request, self.template_name, {
  141. 'cluser': cluster,
  142. 'form': form,
  143. 'return_url': cluster.get_absolute_url(),
  144. })
  145. class ClusterRemoveDevicesView(PermissionRequiredMixin, View):
  146. permission_required = 'virtualization.change_cluster'
  147. form = forms.ClusterRemoveDevicesForm
  148. template_name = 'utilities/obj_bulk_remove.html'
  149. def post(self, request, pk):
  150. cluster = get_object_or_404(Cluster, pk=pk)
  151. if '_confirm' in request.POST:
  152. form = self.form(request.POST)
  153. if form.is_valid():
  154. # Remove the selected Devices from the Cluster
  155. devices = form.cleaned_data['pk']
  156. Device.objects.filter(pk__in=devices).update(cluster=None)
  157. messages.success(request, "Removed {} devices from cluster {}".format(
  158. len(devices), cluster
  159. ))
  160. return redirect(cluster.get_absolute_url())
  161. else:
  162. form = self.form(initial={'pk': request.POST.getlist('pk')})
  163. selected_objects = Device.objects.filter(pk__in=form.initial['pk'])
  164. device_table = DeviceTable(list(selected_objects), orderable=False)
  165. return render(request, self.template_name, {
  166. 'form': form,
  167. 'parent_obj': cluster,
  168. 'table': device_table,
  169. 'obj_type_plural': 'devices',
  170. 'return_url': cluster.get_absolute_url(),
  171. })
  172. #
  173. # Virtual machines
  174. #
  175. class VirtualMachineListView(ObjectListView):
  176. queryset = VirtualMachine.objects.select_related('cluster', 'tenant', 'role', 'primary_ip4', 'primary_ip6')
  177. filter = filters.VirtualMachineFilter
  178. filter_form = forms.VirtualMachineFilterForm
  179. table = tables.VirtualMachineDetailTable
  180. template_name = 'virtualization/virtualmachine_list.html'
  181. class VirtualMachineView(View):
  182. def get(self, request, pk):
  183. virtualmachine = get_object_or_404(VirtualMachine.objects.select_related('tenant__group'), pk=pk)
  184. interfaces = Interface.objects.filter(virtual_machine=virtualmachine)
  185. services = Service.objects.filter(virtual_machine=virtualmachine)
  186. return render(request, 'virtualization/virtualmachine.html', {
  187. 'virtualmachine': virtualmachine,
  188. 'interfaces': interfaces,
  189. 'services': services,
  190. })
  191. class VirtualMachineConfigContextView(ObjectConfigContextView):
  192. object_class = VirtualMachine
  193. base_template = 'virtualization/virtualmachine.html'
  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. queryset = VirtualMachine.objects.select_related('cluster', 'tenant', 'role')
  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. queryset = VirtualMachine.objects.select_related('cluster', 'tenant', 'role')
  221. filter = filters.VirtualMachineFilter
  222. table = tables.VirtualMachineTable
  223. default_return_url = 'virtualization:virtualmachine_list'
  224. #
  225. # VM interfaces
  226. #
  227. class InterfaceCreateView(PermissionRequiredMixin, ComponentCreateView):
  228. permission_required = 'dcim.add_interface'
  229. parent_model = VirtualMachine
  230. parent_field = 'virtual_machine'
  231. model = Interface
  232. form = forms.InterfaceCreateForm
  233. model_form = forms.InterfaceForm
  234. template_name = 'virtualization/virtualmachine_component_add.html'
  235. class InterfaceEditView(PermissionRequiredMixin, ObjectEditView):
  236. permission_required = 'dcim.change_interface'
  237. model = Interface
  238. model_form = forms.InterfaceForm
  239. template_name = 'virtualization/interface_edit.html'
  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. queryset = Interface.objects.all()
  246. parent_model = VirtualMachine
  247. table = tables.InterfaceTable
  248. form = forms.InterfaceBulkEditForm
  249. class InterfaceBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
  250. permission_required = 'dcim.delete_interface'
  251. queryset = Interface.objects.all()
  252. parent_model = 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'