views.py 8.36 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.shortcuts import redirect, get_object_or_404
23
from django.core.exceptions import PermissionDenied, SuspiciousOperation
24
from django.core.urlresolvers import reverse
Kálmán Viktor committed
25 26 27 28

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

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


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


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

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

        if not user.is_superuser:
            raise SuspiciousOperation

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

        return redirect(request.get_absolute_url())

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

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

91 92 93
        context = super(RequestDetail, self).get_context_data(**kwargs)

        context['action'] = request.action
94
        context['accept_states'] = ResourcesOperation.accept_states
95 96 97

        return context

Kálmán Viktor committed
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112

class TemplateAccessTypeDetail(LoginRequiredMixin, SuperuserRequiredMixin,
                               UpdateView):
    model = TemplateAccessType
    template_name = "request/template-type-form.html"
    form_class = TemplateAccessTypeForm


class TemplateAccessTypeCreate(LoginRequiredMixin, SuperuserRequiredMixin,
                               CreateView):
    model = TemplateAccessType
    template_name = "request/template-type-form.html"
    form_class = TemplateAccessTypeForm


113 114 115 116 117 118 119 120 121
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")


Kálmán Viktor committed
122 123 124 125 126 127 128 129 130 131 132 133
class LeaseTypeDetail(LoginRequiredMixin, SuperuserRequiredMixin, UpdateView):
    model = LeaseType
    template_name = "request/lease-type-form.html"
    form_class = LeaseTypeForm


class LeaseTypeCreate(LoginRequiredMixin, SuperuserRequiredMixin, CreateView):
    model = LeaseType
    template_name = "request/lease-type-form.html"
    form_class = LeaseTypeForm


134 135 136 137 138 139 140 141
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
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
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


class TemplateRequestView(FormView):
    form_class = TemplateRequestForm
    template_name = "request/request-template.html"

161 162 163 164 165
    def get_form_kwargs(self):
        kwargs = super(TemplateRequestView, self).get_form_kwargs()
        kwargs['request'] = self.request
        return kwargs

Kálmán Viktor committed
166 167 168 169 170 171 172 173 174 175 176 177 178
    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,
179
            message=data['message'],
Kálmán Viktor committed
180 181 182 183 184 185
            type=Request.TYPES.template,
            action=ta
        )
        req.save()

        return redirect("/")
186 187


188
class VmRequestMixin(object):
189 190 191 192 193
    def get_vm(self):
        return get_object_or_404(Instance, pk=self.kwargs['vm_pk'])

    def dispatch(self, *args, **kwargs):
        vm = self.get_vm()
194
        user = self.request.user
195
        if not vm.has_level(user, self.user_level):
196
            raise PermissionDenied()
197
        return super(VmRequestMixin, self).dispatch(*args, **kwargs)
198

199
    def get_context_data(self, **kwargs):
200
        context = super(VmRequestMixin, self).get_context_data(**kwargs)
201
        context['vm'] = self.get_vm()
202 203
        return context

204
    def get_form_kwargs(self):
205
        kwargs = super(VmRequestMixin, self).get_form_kwargs()
206 207 208
        kwargs['request'] = self.request
        return kwargs

209
    def form_valid(self, form):
210 211 212 213 214 215 216 217 218
        raise NotImplementedError


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

    def form_valid(self, form):
219 220 221 222 223 224 225 226 227 228 229 230
        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,
231
            message=data['message'],
232 233 234 235 236 237
            type=Request.TYPES.lease,
            action=el
        )
        req.save()

        return redirect(vm.get_absolute_url())
238 239


240
class ResourceRequestView(VmRequestMixin, FormView):
241 242
    form_class = ResourceRequestForm
    template_name = "request/request-resource.html"
243
    user_level = "user"
244 245 246 247

    def get_form_kwargs(self):
        kwargs = super(ResourceRequestView, self).get_form_kwargs()
        kwargs['can_edit'] = True
248
        kwargs['instance'] = self.get_vm()
249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273
        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,
274
            message=data['message'],
275 276 277 278 279 280
            type=Request.TYPES.resource,
            action=rc
        )
        req.save()

        return redirect(vm.get_absolute_url())