views.py 8.89 KB
Newer Older
Kálmán Viktor committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
# Copyright 2014 Budapest University of Technology and Economics (BME IK)
#
# This file is part of CIRCLE Cloud.
#
# CIRCLE is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# CIRCLE is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along
# with CIRCLE.  If not, see <http://www.gnu.org/licenses/>.
Kálmán Viktor committed
17 18 19
from __future__ import unicode_literals, absolute_import

from django.views.generic import (
20
    UpdateView, TemplateView, DetailView, CreateView, FormView, DeleteView,
Kálmán Viktor committed
21
)
22
from django.contrib.messages.views import SuccessMessageMixin
23
from django.shortcuts import redirect, get_object_or_404
24
from django.core.exceptions import PermissionDenied, SuspiciousOperation
25
from django.core.urlresolvers import reverse
26
from django.utils.translation import ugettext as _
Kálmán Viktor committed
27 28 29 30

from braces.views import SuperuserRequiredMixin, LoginRequiredMixin
from django_tables2 import SingleTableView

31 32
from request.models import (
    Request, TemplateAccessType, LeaseType, TemplateAccessAction,
33
    ExtendLeaseAction, ResourceChangeAction,
34 35
)
from vm.models import Instance
36
from vm.operations import ResourcesOperation
Kálmán Viktor committed
37 38 39 40
from request.tables import (
    RequestTable, TemplateAccessTypeTable, LeaseTypeTable,
)
from request.forms import (
41
    LeaseTypeForm, TemplateAccessTypeForm, TemplateRequestForm,
42
    LeaseRequestForm, ResourceRequestForm,
Kálmán Viktor committed
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
)


class RequestList(LoginRequiredMixin, SuperuserRequiredMixin, SingleTableView):
    model = Request
    table_class = RequestTable
    template_name = "request/list.html"

    def get_context_data(self, **kwargs):
        context = super(RequestList, self).get_context_data(**kwargs)
        context['statuses'] = Request.STATUSES
        return context

    def get_table_data(self):
        data = Request.objects.all()
        status = self.request.GET.get("status")
        if status:
            data = data.filter(status=status)

        return data


65
class RequestDetail(LoginRequiredMixin, DetailView):
Kálmán Viktor committed
66 67 68
    model = Request
    template_name = "request/detail.html"

69
    def post(self, *args, **kwargs):
70 71 72 73 74 75 76
        user = self.request.user
        request = self.get_object()  # not self.request!

        if not user.is_superuser:
            raise SuspiciousOperation

        if self.get_object().status == "PENDING":
77
            accept = self.request.POST.get("accept")
78
            reason = self.request.POST.get("reason")
79 80 81
            if accept:
                request.accept(user)
            else:
82
                request.decline(user, reason)
83 84 85

        return redirect(request.get_absolute_url())

86 87
    def get_context_data(self, **kwargs):
        request = self.object
88 89 90 91 92
        user = self.request.user

        if not user.is_superuser and request.user != user:
            raise SuspiciousOperation

93 94 95
        context = super(RequestDetail, self).get_context_data(**kwargs)

        context['action'] = request.action
96
        context['accept_states'] = ResourcesOperation.accept_states
97 98 99

        return context

Kálmán Viktor committed
100 101

class TemplateAccessTypeDetail(LoginRequiredMixin, SuperuserRequiredMixin,
102
                               SuccessMessageMixin, UpdateView):
Kálmán Viktor committed
103 104 105
    model = TemplateAccessType
    template_name = "request/template-type-form.html"
    form_class = TemplateAccessTypeForm
106
    success_message = _("Template access type successfully updated.")
Kálmán Viktor committed
107 108 109


class TemplateAccessTypeCreate(LoginRequiredMixin, SuperuserRequiredMixin,
110
                               SuccessMessageMixin, CreateView):
Kálmán Viktor committed
111 112 113
    model = TemplateAccessType
    template_name = "request/template-type-form.html"
    form_class = TemplateAccessTypeForm
114
    success_message = _("New template access type successfully created.")
Kálmán Viktor committed
115 116


117 118 119 120 121 122 123 124 125
class TemplateAccessTypeDelete(LoginRequiredMixin, SuperuserRequiredMixin,
                               DeleteView):
    model = TemplateAccessType
    template_name = "dashboard/confirm/base-delete.html"

    def get_success_url(self):
        return reverse("request.views.type-list")


126 127
class LeaseTypeDetail(LoginRequiredMixin, SuperuserRequiredMixin,
                      SuccessMessageMixin, UpdateView):
Kálmán Viktor committed
128 129 130
    model = LeaseType
    template_name = "request/lease-type-form.html"
    form_class = LeaseTypeForm
131
    success_message = _("Lease type successfully updated.")
Kálmán Viktor committed
132 133


134 135
class LeaseTypeCreate(LoginRequiredMixin, SuperuserRequiredMixin,
                      SuccessMessageMixin, CreateView):
Kálmán Viktor committed
136 137 138
    model = LeaseType
    template_name = "request/lease-type-form.html"
    form_class = LeaseTypeForm
139
    success_message = _("New lease type successfully created.")
Kálmán Viktor committed
140 141


142 143 144 145 146 147 148 149
class LeaseTypeDelete(LoginRequiredMixin, SuperuserRequiredMixin, DeleteView):
    model = LeaseType
    template_name = "dashboard/confirm/base-delete.html"

    def get_success_url(self):
        return reverse("request.views.type-list")


Kálmán Viktor committed
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
class RequestTypeList(LoginRequiredMixin, SuperuserRequiredMixin,
                      TemplateView):
    template_name = "request/type-list.html"

    def get_context_data(self, **kwargs):
        context = super(RequestTypeList, self).get_context_data(**kwargs)

        context['lease_table'] = LeaseTypeTable(
            LeaseType.objects.all(), request=self.request)
        context['template_table'] = TemplateAccessTypeTable(
            TemplateAccessType.objects.all(), request=self.request)

        return context


165
class TemplateRequestView(LoginRequiredMixin, FormView):
Kálmán Viktor committed
166 167 168
    form_class = TemplateRequestForm
    template_name = "request/request-template.html"

169 170 171 172 173
    def get_form_kwargs(self):
        kwargs = super(TemplateRequestView, self).get_form_kwargs()
        kwargs['request'] = self.request
        return kwargs

Kálmán Viktor committed
174 175 176 177 178 179 180 181 182 183 184 185 186
    def form_valid(self, form):
        data = form.cleaned_data
        user = self.request.user

        ta = TemplateAccessAction(
            template_type=data['template'],
            level=data['level'],
            user=user,
        )
        ta.save()

        req = Request(
            user=user,
187
            message=data['message'],
Kálmán Viktor committed
188 189 190 191 192 193
            type=Request.TYPES.template,
            action=ta
        )
        req.save()

        return redirect("/")
194 195


196
class VmRequestMixin(LoginRequiredMixin, object):
197 198 199 200 201
    def get_vm(self):
        return get_object_or_404(Instance, pk=self.kwargs['vm_pk'])

    def dispatch(self, *args, **kwargs):
        vm = self.get_vm()
202
        user = self.request.user
203
        if not vm.has_level(user, self.user_level):
204
            raise PermissionDenied()
205
        return super(VmRequestMixin, self).dispatch(*args, **kwargs)
206

207
    def get_context_data(self, **kwargs):
208
        context = super(VmRequestMixin, self).get_context_data(**kwargs)
209
        context['vm'] = self.get_vm()
210 211
        return context

212
    def get_form_kwargs(self):
213
        kwargs = super(VmRequestMixin, self).get_form_kwargs()
214 215 216
        kwargs['request'] = self.request
        return kwargs

217
    def form_valid(self, form):
218 219 220 221 222 223 224 225 226
        raise NotImplementedError


class LeaseRequestView(VmRequestMixin, FormView):
    form_class = LeaseRequestForm
    template_name = "request/request-lease.html"
    user_level = "operator"

    def form_valid(self, form):
227 228 229 230 231 232 233 234 235 236 237 238
        data = form.cleaned_data
        user = self.request.user
        vm = self.get_vm()

        el = ExtendLeaseAction(
            lease_type=data['lease'],
            instance=vm,
        )
        el.save()

        req = Request(
            user=user,
239
            message=data['message'],
240 241 242 243 244 245
            type=Request.TYPES.lease,
            action=el
        )
        req.save()

        return redirect(vm.get_absolute_url())
246 247


248
class ResourceRequestView(VmRequestMixin, FormView):
249 250
    form_class = ResourceRequestForm
    template_name = "request/request-resource.html"
251
    user_level = "user"
252 253 254 255

    def get_form_kwargs(self):
        kwargs = super(ResourceRequestView, self).get_form_kwargs()
        kwargs['can_edit'] = True
256
        kwargs['instance'] = self.get_vm()
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
        return kwargs

    def get_initial(self):
        vm = self.get_vm()
        initial = super(ResourceRequestView, self).get_initial()
        initial['num_cores'] = vm.num_cores
        initial['priority'] = vm.priority
        initial['ram_size'] = vm.ram_size
        return initial

    def form_valid(self, form):
        vm = self.get_vm()
        data = form.cleaned_data
        user = self.request.user

        rc = ResourceChangeAction(
            instance=vm,
            num_cores=data['num_cores'],
            priority=data['priority'],
            ram_size=data['ram_size'],
        )
        rc.save()

        req = Request(
            user=user,
282
            message=data['message'],
283 284 285 286 287 288
            type=Request.TYPES.resource,
            action=rc
        )
        req.save()

        return redirect(vm.get_absolute_url())