views.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. from django.contrib import messages
  2. from django.contrib.auth.mixins import PermissionRequiredMixin
  3. from django.db import transaction
  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 dcim.models import Device, Interface
  8. from dcim.tables import DeviceTable
  9. from extras.views import ObjectConfigContextView
  10. from ipam.models import Service
  11. from utilities.views import (
  12. BulkComponentCreateView, BulkDeleteView, BulkEditView, BulkImportView, ComponentCreateView, ObjectView,
  13. ObjectDeleteView, 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. class ClusterTypeEditView(ObjectEditView):
  24. queryset = ClusterType.objects.all()
  25. model_form = forms.ClusterTypeForm
  26. default_return_url = 'virtualization:clustertype_list'
  27. class ClusterTypeBulkImportView(BulkImportView):
  28. queryset = ClusterType.objects.all()
  29. model_form = forms.ClusterTypeCSVForm
  30. table = tables.ClusterTypeTable
  31. default_return_url = 'virtualization:clustertype_list'
  32. class ClusterTypeBulkDeleteView(BulkDeleteView):
  33. queryset = ClusterType.objects.annotate(cluster_count=Count('clusters'))
  34. table = tables.ClusterTypeTable
  35. default_return_url = 'virtualization:clustertype_list'
  36. #
  37. # Cluster groups
  38. #
  39. class ClusterGroupListView(ObjectListView):
  40. queryset = ClusterGroup.objects.annotate(cluster_count=Count('clusters'))
  41. table = tables.ClusterGroupTable
  42. class ClusterGroupEditView(ObjectEditView):
  43. queryset = ClusterGroup.objects.all()
  44. model_form = forms.ClusterGroupForm
  45. default_return_url = 'virtualization:clustergroup_list'
  46. class ClusterGroupBulkImportView(BulkImportView):
  47. queryset = ClusterGroup.objects.all()
  48. model_form = forms.ClusterGroupCSVForm
  49. table = tables.ClusterGroupTable
  50. default_return_url = 'virtualization:clustergroup_list'
  51. class ClusterGroupBulkDeleteView(BulkDeleteView):
  52. queryset = ClusterGroup.objects.annotate(cluster_count=Count('clusters'))
  53. table = tables.ClusterGroupTable
  54. default_return_url = 'virtualization:clustergroup_list'
  55. #
  56. # Clusters
  57. #
  58. class ClusterListView(ObjectListView):
  59. queryset = Cluster.objects.prefetch_related('type', 'group', 'site', 'tenant')
  60. table = tables.ClusterTable
  61. filterset = filters.ClusterFilterSet
  62. filterset_form = forms.ClusterFilterForm
  63. class ClusterView(ObjectView):
  64. queryset = Cluster.objects.all()
  65. def get(self, request, pk):
  66. cluster = get_object_or_404(self.queryset, pk=pk)
  67. devices = Device.objects.filter(cluster=cluster).prefetch_related(
  68. 'site', 'rack', 'tenant', 'device_type__manufacturer'
  69. )
  70. device_table = DeviceTable(list(devices), orderable=False)
  71. if request.user.has_perm('virtualization.change_cluster'):
  72. device_table.columns.show('pk')
  73. return render(request, 'virtualization/cluster.html', {
  74. 'cluster': cluster,
  75. 'device_table': device_table,
  76. })
  77. class ClusterEditView(ObjectEditView):
  78. template_name = 'virtualization/cluster_edit.html'
  79. queryset = Cluster.objects.all()
  80. model_form = forms.ClusterForm
  81. class ClusterDeleteView(ObjectDeleteView):
  82. queryset = Cluster.objects.all()
  83. default_return_url = 'virtualization:cluster_list'
  84. class ClusterBulkImportView(BulkImportView):
  85. queryset = Cluster.objects.all()
  86. model_form = forms.ClusterCSVForm
  87. table = tables.ClusterTable
  88. default_return_url = 'virtualization:cluster_list'
  89. class ClusterBulkEditView(BulkEditView):
  90. queryset = Cluster.objects.prefetch_related('type', 'group', 'site')
  91. filterset = filters.ClusterFilterSet
  92. table = tables.ClusterTable
  93. form = forms.ClusterBulkEditForm
  94. default_return_url = 'virtualization:cluster_list'
  95. class ClusterBulkDeleteView(BulkDeleteView):
  96. queryset = Cluster.objects.prefetch_related('type', 'group', 'site')
  97. filterset = filters.ClusterFilterSet
  98. table = tables.ClusterTable
  99. default_return_url = 'virtualization:cluster_list'
  100. class ClusterAddDevicesView(ObjectEditView):
  101. queryset = Cluster.objects.all()
  102. form = forms.ClusterAddDevicesForm
  103. template_name = 'virtualization/cluster_add_devices.html'
  104. def get(self, request, pk):
  105. cluster = get_object_or_404(self.queryset, pk=pk)
  106. form = self.form(cluster, initial=request.GET)
  107. return render(request, self.template_name, {
  108. 'cluster': cluster,
  109. 'form': form,
  110. 'return_url': reverse('virtualization:cluster', kwargs={'pk': pk}),
  111. })
  112. def post(self, request, pk):
  113. cluster = get_object_or_404(self.queryset, pk=pk)
  114. form = self.form(cluster, request.POST)
  115. if form.is_valid():
  116. device_pks = form.cleaned_data['devices']
  117. with transaction.atomic():
  118. # Assign the selected Devices to the Cluster
  119. for device in Device.objects.filter(pk__in=device_pks):
  120. device.cluster = cluster
  121. device.save()
  122. messages.success(request, "Added {} devices to cluster {}".format(
  123. len(device_pks), cluster
  124. ))
  125. return redirect(cluster.get_absolute_url())
  126. return render(request, self.template_name, {
  127. 'cluster': cluster,
  128. 'form': form,
  129. 'return_url': cluster.get_absolute_url(),
  130. })
  131. class ClusterRemoveDevicesView(ObjectEditView):
  132. queryset = Cluster.objects.all()
  133. form = forms.ClusterRemoveDevicesForm
  134. template_name = 'utilities/obj_bulk_remove.html'
  135. def post(self, request, pk):
  136. cluster = get_object_or_404(self.queryset, pk=pk)
  137. if '_confirm' in request.POST:
  138. form = self.form(request.POST)
  139. if form.is_valid():
  140. device_pks = form.cleaned_data['pk']
  141. with transaction.atomic():
  142. # Remove the selected Devices from the Cluster
  143. for device in Device.objects.filter(pk__in=device_pks):
  144. device.cluster = None
  145. device.save()
  146. messages.success(request, "Removed {} devices from cluster {}".format(
  147. len(device_pks), cluster
  148. ))
  149. return redirect(cluster.get_absolute_url())
  150. else:
  151. form = self.form(initial={'pk': request.POST.getlist('pk')})
  152. selected_objects = Device.objects.filter(pk__in=form.initial['pk'])
  153. device_table = DeviceTable(list(selected_objects), orderable=False)
  154. return render(request, self.template_name, {
  155. 'form': form,
  156. 'parent_obj': cluster,
  157. 'table': device_table,
  158. 'obj_type_plural': 'devices',
  159. 'return_url': cluster.get_absolute_url(),
  160. })
  161. #
  162. # Virtual machines
  163. #
  164. class VirtualMachineListView(ObjectListView):
  165. queryset = VirtualMachine.objects.prefetch_related('cluster', 'tenant', 'role', 'primary_ip4', 'primary_ip6')
  166. filterset = filters.VirtualMachineFilterSet
  167. filterset_form = forms.VirtualMachineFilterForm
  168. table = tables.VirtualMachineDetailTable
  169. template_name = 'virtualization/virtualmachine_list.html'
  170. class VirtualMachineView(ObjectView):
  171. queryset = VirtualMachine.objects.prefetch_related('tenant__group')
  172. def get(self, request, pk):
  173. virtualmachine = get_object_or_404(self.queryset, pk=pk)
  174. interfaces = Interface.objects.filter(virtual_machine=virtualmachine)
  175. services = Service.objects.filter(virtual_machine=virtualmachine)
  176. return render(request, 'virtualization/virtualmachine.html', {
  177. 'virtualmachine': virtualmachine,
  178. 'interfaces': interfaces,
  179. 'services': services,
  180. })
  181. class VirtualMachineConfigContextView(PermissionRequiredMixin, ObjectConfigContextView):
  182. permission_required = 'virtualization.view_virtualmachine'
  183. object_class = VirtualMachine
  184. base_template = 'virtualization/virtualmachine.html'
  185. class VirtualMachineEditView(ObjectEditView):
  186. queryset = VirtualMachine.objects.all()
  187. model_form = forms.VirtualMachineForm
  188. template_name = 'virtualization/virtualmachine_edit.html'
  189. default_return_url = 'virtualization:virtualmachine_list'
  190. class VirtualMachineDeleteView(ObjectDeleteView):
  191. queryset = VirtualMachine.objects.all()
  192. default_return_url = 'virtualization:virtualmachine_list'
  193. class VirtualMachineBulkImportView(BulkImportView):
  194. queryset = VirtualMachine.objects.all()
  195. model_form = forms.VirtualMachineCSVForm
  196. table = tables.VirtualMachineTable
  197. default_return_url = 'virtualization:virtualmachine_list'
  198. class VirtualMachineBulkEditView(BulkEditView):
  199. queryset = VirtualMachine.objects.prefetch_related('cluster', 'tenant', 'role')
  200. filterset = filters.VirtualMachineFilterSet
  201. table = tables.VirtualMachineTable
  202. form = forms.VirtualMachineBulkEditForm
  203. default_return_url = 'virtualization:virtualmachine_list'
  204. class VirtualMachineBulkDeleteView(BulkDeleteView):
  205. queryset = VirtualMachine.objects.prefetch_related('cluster', 'tenant', 'role')
  206. filterset = filters.VirtualMachineFilterSet
  207. table = tables.VirtualMachineTable
  208. default_return_url = 'virtualization:virtualmachine_list'
  209. #
  210. # VM interfaces
  211. #
  212. class InterfaceCreateView(ComponentCreateView):
  213. queryset = Interface.objects.all()
  214. form = forms.InterfaceCreateForm
  215. model_form = forms.InterfaceForm
  216. template_name = 'virtualization/virtualmachine_component_add.html'
  217. class InterfaceEditView(ObjectEditView):
  218. queryset = Interface.objects.all()
  219. model_form = forms.InterfaceForm
  220. template_name = 'virtualization/interface_edit.html'
  221. class InterfaceDeleteView(ObjectDeleteView):
  222. queryset = Interface.objects.all()
  223. class InterfaceBulkEditView(BulkEditView):
  224. queryset = Interface.objects.all()
  225. table = tables.InterfaceTable
  226. form = forms.InterfaceBulkEditForm
  227. class InterfaceBulkDeleteView(BulkDeleteView):
  228. queryset = Interface.objects.all()
  229. table = tables.InterfaceTable
  230. #
  231. # Bulk Device component creation
  232. #
  233. class VirtualMachineBulkAddInterfaceView(BulkComponentCreateView):
  234. parent_model = VirtualMachine
  235. parent_field = 'virtual_machine'
  236. form = forms.InterfaceBulkCreateForm
  237. queryset = Interface.objects.all()
  238. model_form = forms.InterfaceForm
  239. filterset = filters.VirtualMachineFilterSet
  240. table = tables.VirtualMachineTable
  241. default_return_url = 'virtualization:virtualmachine_list'