1 from django.contrib.auth.mixins import LoginRequiredMixin

2 from django.http import HttpResponseRedirect

3 from django.shortcuts import get_object_or_404, redirect

4 from django.urls import reverse_lazy

5 from django.views.generic import CreateView, DeleteView, DetailView, UpdateView, View

6

7 from meshadmin.server.networks.mixins import NetworkPermissionMixin

8 from meshadmin.server.networks.models import ConfigRollout, Host, Network

9

10

11 class RolloutCreateView(LoginRequiredMixin, NetworkPermissionMixin, CreateView):

12 model = ConfigRollout

13 template_name = "networks/rollout/create.html"

14 fields = ["name", "notes"]

15

16 def get_network(self):

17 network_id = self.kwargs.get("network_id")

18 if network_id:

19 return get_object_or_404(Network, id=network_id)

20 return None

21

22 def get_context_data(self, **kwargs):

23 context = super().get_context_data(**kwargs)

24 network = self.get_network()

25 context["network"] = network

26

27 host_ids = self.request.GET.get("hosts", "").split(",")

28 if host_ids and host_ids[0]:

29 context["preselected_hosts"] = Host.objects.filter(

30 id__in=host_ids, network=network

31 )

32

33 context["hosts"] = Host.objects.filter(network=network)

34 return context

35

36 def form_valid(self, form):

37 form.instance.network_id = self.kwargs["network_id"]

38 response = super().form_valid(form)

39

40 selected_hosts = self.request.POST.getlist("hosts")

41 if selected_hosts:

42 self.object.target_hosts.set(selected_hosts)

43 Host.objects.filter(id__in=selected_hosts).update(config_freeze=True)

44

45 return response

46

47 def get_success_url(self):

48 return (

49 reverse_lazy(

50 "networks:network-detail", kwargs={"pk": self.kwargs["network_id"]}

51 )

52 + "#rollouts-section"

53 )

54

55

56 class RolloutDetailView(LoginRequiredMixin, NetworkPermissionMixin, DetailView):

57 model = ConfigRollout

58 template_name = "networks/rollout/detail.html"

59

60 def get_network(self):

61 return self.get_object().network

62

63 def get_context_data(self, **kwargs):

64 context = super().get_context_data(**kwargs)

65 context["pending_hosts"] = self.object.target_hosts.exclude(

66 id__in=self.object.completed_hosts.values_list("id", flat=True)

67 )

68 return context

69

70

71 class UnfreezeHostConfigView(LoginRequiredMixin, NetworkPermissionMixin, View):

72 def get_network(self):

73 rollout = get_object_or_404(ConfigRollout, id=self.kwargs.get("pk"))

74 return rollout.network

75

76 def post(self, request, pk):

77 rollout = get_object_or_404(ConfigRollout, id=pk)

78 host_id = request.POST.get("host_id")

79 if host_id:

80 host = get_object_or_404(Host, id=host_id)

81 if host not in rollout.completed_hosts.all():

82 try:

83 host.config_freeze = False

84 host.save()

85 rollout.completed_hosts.add(host)

86 except Exception:

87 rollout.status = "FAILED"

88 rollout.save()

89 else:

90 pending_hosts = rollout.target_hosts.exclude(

91 id__in=rollout.completed_hosts.values_list("id", flat=True)

92 )

93 for host in pending_hosts:

94 try:

95 host.config_freeze = False

96 host.save()

97 rollout.completed_hosts.add(host)

98 except Exception:

99 rollout.status = "FAILED"

100 rollout.save()

101 return redirect("networks:rollout-detail", pk=pk)

102

103 if not rollout.target_hosts.exclude(

104 id__in=rollout.completed_hosts.values_list("id", flat=True)

105 ).exists():

106 rollout.status = "COMPLETED"

107 rollout.save()

108

109 return redirect("networks:rollout-detail", pk=pk)

110

111

112 class RolloutUpdateView(LoginRequiredMixin, NetworkPermissionMixin, UpdateView):

113 model = ConfigRollout

114 template_name = "networks/rollout/edit.html"

115 fields = ["name", "notes"]

116

117 def get_network(self):

118 return self.get_object().network

119

120 def get_context_data(self, **kwargs):

121 context = super().get_context_data(**kwargs)

122 context["hosts"] = Host.objects.filter(network=self.get_network())

123 return context

124

125 def form_valid(self, form):

126 response = super().form_valid(form)

127 selected_hosts = self.request.POST.getlist("hosts")

128 if selected_hosts:

129 removed_hosts = self.object.target_hosts.exclude(id__in=selected_hosts)

130 removed_hosts.update(config_freeze=False)

131 self.object.target_hosts.set(selected_hosts)

132 Host.objects.filter(id__in=selected_hosts).update(config_freeze=True)

133

134 return response

135

136 def get_success_url(self):

137 return reverse_lazy("networks:rollout-detail", kwargs={"pk": self.object.pk})

138

139

140 class RolloutDeleteView(LoginRequiredMixin, NetworkPermissionMixin, DeleteView):

141 model = ConfigRollout

142 template_name = "networks/rollout/delete.html"

143

144 def get_network(self):

145 return self.get_object().network

146

147 def post(self, request, *args, **kwargs):

148 self.object = self.get_object()

149 self.object.target_hosts.all().update(config_freeze=False)

150 network_id = self.object.network_id

151 self.object.delete()

152 return HttpResponseRedirect(

153 reverse_lazy("networks:network-detail", kwargs={"pk": network_id})

154 + "#rollouts-section"

155 )