views.py 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. from django.contrib import messages
  2. from django.db import transaction
  3. from django.db.models import Q
  4. from django.shortcuts import get_object_or_404, redirect, render
  5. from netbox.views import generic
  6. from utilities.forms import ConfirmationForm
  7. from utilities.utils import count_related
  8. from . import filtersets, forms, tables
  9. from .models import *
  10. #
  11. # Providers
  12. #
  13. class ProviderListView(generic.ObjectListView):
  14. queryset = Provider.objects.annotate(
  15. count_circuits=count_related(Circuit, 'provider')
  16. )
  17. filterset = filtersets.ProviderFilterSet
  18. filterset_form = forms.ProviderFilterForm
  19. table = tables.ProviderTable
  20. class ProviderView(generic.ObjectView):
  21. queryset = Provider.objects.all()
  22. def get_extra_context(self, request, instance):
  23. circuits = Circuit.objects.restrict(request.user, 'view').filter(
  24. provider=instance
  25. ).prefetch_related(
  26. 'type', 'tenant', 'terminations__site'
  27. )
  28. circuits_table = tables.CircuitTable(circuits, user=request.user, exclude=('provider',))
  29. circuits_table.configure(request)
  30. return {
  31. 'circuits_table': circuits_table,
  32. }
  33. class ProviderEditView(generic.ObjectEditView):
  34. queryset = Provider.objects.all()
  35. form = forms.ProviderForm
  36. class ProviderDeleteView(generic.ObjectDeleteView):
  37. queryset = Provider.objects.all()
  38. class ProviderBulkImportView(generic.BulkImportView):
  39. queryset = Provider.objects.all()
  40. model_form = forms.ProviderCSVForm
  41. table = tables.ProviderTable
  42. class ProviderBulkEditView(generic.BulkEditView):
  43. queryset = Provider.objects.annotate(
  44. count_circuits=count_related(Circuit, 'provider')
  45. )
  46. filterset = filtersets.ProviderFilterSet
  47. table = tables.ProviderTable
  48. form = forms.ProviderBulkEditForm
  49. class ProviderBulkDeleteView(generic.BulkDeleteView):
  50. queryset = Provider.objects.annotate(
  51. count_circuits=count_related(Circuit, 'provider')
  52. )
  53. filterset = filtersets.ProviderFilterSet
  54. table = tables.ProviderTable
  55. #
  56. # Provider networks
  57. #
  58. class ProviderNetworkListView(generic.ObjectListView):
  59. queryset = ProviderNetwork.objects.all()
  60. filterset = filtersets.ProviderNetworkFilterSet
  61. filterset_form = forms.ProviderNetworkFilterForm
  62. table = tables.ProviderNetworkTable
  63. class ProviderNetworkView(generic.ObjectView):
  64. queryset = ProviderNetwork.objects.all()
  65. def get_extra_context(self, request, instance):
  66. circuits = Circuit.objects.restrict(request.user, 'view').filter(
  67. Q(termination_a__provider_network=instance.pk) |
  68. Q(termination_z__provider_network=instance.pk)
  69. ).prefetch_related(
  70. 'type', 'tenant', 'terminations__site'
  71. )
  72. circuits_table = tables.CircuitTable(circuits, user=request.user)
  73. circuits_table.configure(request)
  74. return {
  75. 'circuits_table': circuits_table,
  76. }
  77. class ProviderNetworkEditView(generic.ObjectEditView):
  78. queryset = ProviderNetwork.objects.all()
  79. form = forms.ProviderNetworkForm
  80. class ProviderNetworkDeleteView(generic.ObjectDeleteView):
  81. queryset = ProviderNetwork.objects.all()
  82. class ProviderNetworkBulkImportView(generic.BulkImportView):
  83. queryset = ProviderNetwork.objects.all()
  84. model_form = forms.ProviderNetworkCSVForm
  85. table = tables.ProviderNetworkTable
  86. class ProviderNetworkBulkEditView(generic.BulkEditView):
  87. queryset = ProviderNetwork.objects.all()
  88. filterset = filtersets.ProviderNetworkFilterSet
  89. table = tables.ProviderNetworkTable
  90. form = forms.ProviderNetworkBulkEditForm
  91. class ProviderNetworkBulkDeleteView(generic.BulkDeleteView):
  92. queryset = ProviderNetwork.objects.all()
  93. filterset = filtersets.ProviderNetworkFilterSet
  94. table = tables.ProviderNetworkTable
  95. #
  96. # Circuit Types
  97. #
  98. class CircuitTypeListView(generic.ObjectListView):
  99. queryset = CircuitType.objects.annotate(
  100. circuit_count=count_related(Circuit, 'type')
  101. )
  102. filterset = filtersets.CircuitTypeFilterSet
  103. filterset_form = forms.CircuitTypeFilterForm
  104. table = tables.CircuitTypeTable
  105. class CircuitTypeView(generic.ObjectView):
  106. queryset = CircuitType.objects.all()
  107. def get_extra_context(self, request, instance):
  108. circuits = Circuit.objects.restrict(request.user, 'view').filter(type=instance)
  109. circuits_table = tables.CircuitTable(circuits, user=request.user, exclude=('type',))
  110. circuits_table.configure(request)
  111. return {
  112. 'circuits_table': circuits_table,
  113. }
  114. class CircuitTypeEditView(generic.ObjectEditView):
  115. queryset = CircuitType.objects.all()
  116. form = forms.CircuitTypeForm
  117. class CircuitTypeDeleteView(generic.ObjectDeleteView):
  118. queryset = CircuitType.objects.all()
  119. class CircuitTypeBulkImportView(generic.BulkImportView):
  120. queryset = CircuitType.objects.all()
  121. model_form = forms.CircuitTypeCSVForm
  122. table = tables.CircuitTypeTable
  123. class CircuitTypeBulkEditView(generic.BulkEditView):
  124. queryset = CircuitType.objects.annotate(
  125. circuit_count=count_related(Circuit, 'type')
  126. )
  127. filterset = filtersets.CircuitTypeFilterSet
  128. table = tables.CircuitTypeTable
  129. form = forms.CircuitTypeBulkEditForm
  130. class CircuitTypeBulkDeleteView(generic.BulkDeleteView):
  131. queryset = CircuitType.objects.annotate(
  132. circuit_count=count_related(Circuit, 'type')
  133. )
  134. table = tables.CircuitTypeTable
  135. #
  136. # Circuits
  137. #
  138. class CircuitListView(generic.ObjectListView):
  139. queryset = Circuit.objects.prefetch_related(
  140. 'provider', 'type', 'tenant', 'termination_a', 'termination_z'
  141. )
  142. filterset = filtersets.CircuitFilterSet
  143. filterset_form = forms.CircuitFilterForm
  144. table = tables.CircuitTable
  145. class CircuitView(generic.ObjectView):
  146. queryset = Circuit.objects.all()
  147. class CircuitEditView(generic.ObjectEditView):
  148. queryset = Circuit.objects.all()
  149. form = forms.CircuitForm
  150. class CircuitDeleteView(generic.ObjectDeleteView):
  151. queryset = Circuit.objects.all()
  152. class CircuitBulkImportView(generic.BulkImportView):
  153. queryset = Circuit.objects.all()
  154. model_form = forms.CircuitCSVForm
  155. table = tables.CircuitTable
  156. class CircuitBulkEditView(generic.BulkEditView):
  157. queryset = Circuit.objects.prefetch_related(
  158. 'provider', 'type', 'tenant', 'terminations'
  159. )
  160. filterset = filtersets.CircuitFilterSet
  161. table = tables.CircuitTable
  162. form = forms.CircuitBulkEditForm
  163. class CircuitBulkDeleteView(generic.BulkDeleteView):
  164. queryset = Circuit.objects.prefetch_related(
  165. 'provider', 'type', 'tenant', 'terminations'
  166. )
  167. filterset = filtersets.CircuitFilterSet
  168. table = tables.CircuitTable
  169. class CircuitSwapTerminations(generic.ObjectEditView):
  170. """
  171. Swap the A and Z terminations of a circuit.
  172. """
  173. queryset = Circuit.objects.all()
  174. def get(self, request, pk):
  175. circuit = get_object_or_404(self.queryset, pk=pk)
  176. form = ConfirmationForm()
  177. # Circuit must have at least one termination to swap
  178. if not circuit.termination_a and not circuit.termination_z:
  179. messages.error(request, "No terminations have been defined for circuit {}.".format(circuit))
  180. return redirect('circuits:circuit', pk=circuit.pk)
  181. return render(request, 'circuits/circuit_terminations_swap.html', {
  182. 'circuit': circuit,
  183. 'termination_a': circuit.termination_a,
  184. 'termination_z': circuit.termination_z,
  185. 'form': form,
  186. 'panel_class': 'light',
  187. 'button_class': 'primary',
  188. 'return_url': circuit.get_absolute_url(),
  189. })
  190. def post(self, request, pk):
  191. circuit = get_object_or_404(self.queryset, pk=pk)
  192. form = ConfirmationForm(request.POST)
  193. if form.is_valid():
  194. termination_a = CircuitTermination.objects.filter(pk=circuit.termination_a_id).first()
  195. termination_z = CircuitTermination.objects.filter(pk=circuit.termination_z_id).first()
  196. if termination_a and termination_z:
  197. # Use a placeholder to avoid an IntegrityError on the (circuit, term_side) unique constraint
  198. with transaction.atomic():
  199. termination_a.term_side = '_'
  200. termination_a.save()
  201. termination_z.term_side = 'A'
  202. termination_z.save()
  203. termination_a.term_side = 'Z'
  204. termination_a.save()
  205. circuit.refresh_from_db()
  206. circuit.termination_a = termination_z
  207. circuit.termination_z = termination_a
  208. circuit.save()
  209. elif termination_a:
  210. termination_a.term_side = 'Z'
  211. termination_a.save()
  212. circuit.refresh_from_db()
  213. circuit.termination_a = None
  214. circuit.save()
  215. else:
  216. termination_z.term_side = 'A'
  217. termination_z.save()
  218. circuit.refresh_from_db()
  219. circuit.termination_z = None
  220. circuit.save()
  221. messages.success(request, f"Swapped terminations for circuit {circuit}.")
  222. return redirect('circuits:circuit', pk=circuit.pk)
  223. return render(request, 'circuits/circuit_terminations_swap.html', {
  224. 'circuit': circuit,
  225. 'termination_a': circuit.termination_a,
  226. 'termination_z': circuit.termination_z,
  227. 'form': form,
  228. 'panel_class': 'default',
  229. 'button_class': 'primary',
  230. 'return_url': circuit.get_absolute_url(),
  231. })
  232. #
  233. # Circuit terminations
  234. #
  235. class CircuitTerminationEditView(generic.ObjectEditView):
  236. queryset = CircuitTermination.objects.all()
  237. form = forms.CircuitTerminationForm
  238. template_name = 'circuits/circuittermination_edit.html'
  239. class CircuitTerminationDeleteView(generic.ObjectDeleteView):
  240. queryset = CircuitTermination.objects.all()