views.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  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. 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. default_return_url = 'virtualization:clustergroup_list'
  55. class ClusterGroupEditView(ClusterGroupCreateView):
  56. permission_required = 'virtualization.change_clustergroup'
  57. class ClusterGroupBulkImportView(PermissionRequiredMixin, BulkImportView):
  58. permission_required = 'virtualization.add_clustergroup'
  59. model_form = forms.ClusterGroupCSVForm
  60. table = tables.ClusterGroupTable
  61. default_return_url = 'virtualization:clustergroup_list'
  62. class ClusterGroupBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
  63. permission_required = 'virtualization.delete_clustergroup'
  64. cls = ClusterGroup
  65. queryset = ClusterGroup.objects.annotate(cluster_count=Count('clusters'))
  66. table = tables.ClusterGroupTable
  67. default_return_url = 'virtualization:clustergroup_list'
  68. #
  69. # Clusters
  70. #
  71. class ClusterListView(ObjectListView):
  72. queryset = Cluster.objects.select_related('type', 'group')
  73. table = tables.ClusterTable
  74. filter = filters.ClusterFilter
  75. filter_form = forms.ClusterFilterForm
  76. template_name = 'virtualization/cluster_list.html'
  77. class ClusterView(View):
  78. def get(self, request, pk):
  79. cluster = get_object_or_404(Cluster, pk=pk)
  80. devices = Device.objects.filter(cluster=cluster).select_related(
  81. 'site', 'rack', 'tenant', 'device_type__manufacturer'
  82. )
  83. device_table = DeviceTable(list(devices), orderable=False)
  84. if request.user.has_perm('virtualization.change_cluster'):
  85. device_table.columns.show('pk')
  86. return render(request, 'virtualization/cluster.html', {
  87. 'cluster': cluster,
  88. 'device_table': device_table,
  89. })
  90. class ClusterCreateView(PermissionRequiredMixin, ObjectEditView):
  91. permission_required = 'virtualization.add_cluster'
  92. template_name = 'virtualization/cluster_edit.html'
  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. virtualmachine = get_object_or_404(VirtualMachine.objects.select_related('tenant__group'), pk=pk)
  187. interfaces = Interface.objects.filter(virtual_machine=virtualmachine)
  188. services = Service.objects.filter(virtual_machine=virtualmachine)
  189. return render(request, 'virtualization/virtualmachine.html', {
  190. 'virtualmachine': virtualmachine,
  191. 'interfaces': interfaces,
  192. 'services': services,
  193. })
  194. class VirtualMachineConfigContextView(ObjectConfigContextView):
  195. object_class = VirtualMachine
  196. base_template = 'virtualization/virtualmachine.html'
  197. class VirtualMachineCreateView(PermissionRequiredMixin, ObjectEditView):
  198. permission_required = 'virtualization.add_virtualmachine'
  199. model = VirtualMachine
  200. model_form = forms.VirtualMachineForm
  201. template_name = 'virtualization/virtualmachine_edit.html'
  202. default_return_url = 'virtualization:virtualmachine_list'
  203. class VirtualMachineEditView(VirtualMachineCreateView):
  204. permission_required = 'virtualization.change_virtualmachine'
  205. class VirtualMachineDeleteView(PermissionRequiredMixin, ObjectDeleteView):
  206. permission_required = 'virtualization.delete_virtualmachine'
  207. model = VirtualMachine
  208. default_return_url = 'virtualization:virtualmachine_list'
  209. class VirtualMachineBulkImportView(PermissionRequiredMixin, BulkImportView):
  210. permission_required = 'virtualization.add_virtualmachine'
  211. model_form = forms.VirtualMachineCSVForm
  212. table = tables.VirtualMachineTable
  213. default_return_url = 'virtualization:virtualmachine_list'
  214. class VirtualMachineBulkEditView(PermissionRequiredMixin, BulkEditView):
  215. permission_required = 'virtualization.change_virtualmachine'
  216. cls = VirtualMachine
  217. queryset = VirtualMachine.objects.select_related('cluster', 'tenant')
  218. filter = filters.VirtualMachineFilter
  219. table = tables.VirtualMachineTable
  220. form = forms.VirtualMachineBulkEditForm
  221. default_return_url = 'virtualization:virtualmachine_list'
  222. class VirtualMachineBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
  223. permission_required = 'virtualization.delete_virtualmachine'
  224. cls = VirtualMachine
  225. queryset = VirtualMachine.objects.select_related('cluster', 'tenant')
  226. filter = filters.VirtualMachineFilter
  227. table = tables.VirtualMachineTable
  228. default_return_url = 'virtualization:virtualmachine_list'
  229. #
  230. # VM interfaces
  231. #
  232. class InterfaceCreateView(PermissionRequiredMixin, ComponentCreateView):
  233. permission_required = 'dcim.add_interface'
  234. parent_model = VirtualMachine
  235. parent_field = 'virtual_machine'
  236. model = Interface
  237. form = forms.InterfaceCreateForm
  238. model_form = forms.InterfaceForm
  239. template_name = 'virtualization/virtualmachine_component_add.html'
  240. class InterfaceEditView(PermissionRequiredMixin, ObjectEditView):
  241. permission_required = 'dcim.change_interface'
  242. model = Interface
  243. model_form = forms.InterfaceForm
  244. template_name = 'virtualization/interface_edit.html'
  245. class InterfaceDeleteView(PermissionRequiredMixin, ObjectDeleteView):
  246. permission_required = 'dcim.delete_interface'
  247. model = Interface
  248. class InterfaceBulkEditView(PermissionRequiredMixin, BulkEditView):
  249. permission_required = 'dcim.change_interface'
  250. cls = Interface
  251. parent_cls = VirtualMachine
  252. table = tables.InterfaceTable
  253. form = forms.InterfaceBulkEditForm
  254. class InterfaceBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
  255. permission_required = 'dcim.delete_interface'
  256. cls = Interface
  257. parent_cls = VirtualMachine
  258. table = tables.InterfaceTable
  259. #
  260. # Bulk Device component creation
  261. #
  262. class VirtualMachineBulkAddInterfaceView(PermissionRequiredMixin, BulkComponentCreateView):
  263. permission_required = 'dcim.add_interface'
  264. parent_model = VirtualMachine
  265. parent_field = 'virtual_machine'
  266. form = forms.VirtualMachineBulkAddInterfaceForm
  267. model = Interface
  268. model_form = forms.InterfaceForm
  269. table = tables.VirtualMachineTable
  270. default_return_url = 'virtualization:virtualmachine_list'