Commit 19d074a6 by Szabolcs Gelencser

Implement lease request decision, fix creation issue

parent 796864de
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2018-05-18 07:30
from __future__ import unicode_literals
import dashboard.models
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import sizefield.models
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('dashboard', '0009_auto_20180517_1630'),
]
operations = [
migrations.RemoveField(
model_name='profile',
name='user_id',
),
migrations.AddField(
model_name='profile',
name='disk_quota',
field=sizefield.models.FileSizeField(default=2147483648, help_text='Disk quota in mebibytes.', verbose_name='disk quota'),
),
migrations.AddField(
model_name='profile',
name='instance_limit',
field=models.IntegerField(default=5),
),
migrations.AddField(
model_name='profile',
name='network_limit',
field=models.IntegerField(default=2, verbose_name=b'Virtual network limit'),
),
migrations.AddField(
model_name='profile',
name='org_id',
field=models.CharField(blank=True, help_text='Unique identifier of the person, e.g. a student number.', max_length=64, null=True, unique=True),
),
migrations.AddField(
model_name='profile',
name='smb_password',
field=models.CharField(default=dashboard.models.pwgen, help_text='Generated password for accessing store from virtual machines.', max_length=20, verbose_name='Samba password'),
),
migrations.AddField(
model_name='profile',
name='two_factor_secret',
field=models.CharField(blank=True, max_length=32, null=True, verbose_name='two factor secret key'),
),
migrations.AddField(
model_name='profile',
name='user',
field=models.OneToOneField(default=0, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
preserve_default=False,
),
]
...@@ -57,7 +57,7 @@ logger = getLogger(__name__) ...@@ -57,7 +57,7 @@ logger = getLogger(__name__)
def pwgen(): def pwgen():
return User.objects.make_random_password() return "TODO: pwgen"#User.objects.make_random_password()
class Message(TimeStampedModel, TimeFramedModel): class Message(TimeStampedModel, TimeFramedModel):
......
...@@ -748,7 +748,7 @@ class VmRenewView(FormOperationMixin, VmOperationView): ...@@ -748,7 +748,7 @@ class VmRenewView(FormOperationMixin, VmOperationView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(VmRenewView, self).get_context_data(**kwargs) context = super(VmRenewView, self).get_context_data(**kwargs)
context['lease_request_form'] = LeaseRequestForm(request=self.request) context['lease_request_form'] = LeaseRequestForm()
context['lease_types'] = LeaseType.objects.exists() context['lease_types'] = LeaseType.objects.exists()
return context return context
# #
......
...@@ -90,11 +90,9 @@ class TemplateRequestForm(InitialFromFileMixin, Form): ...@@ -90,11 +90,9 @@ class TemplateRequestForm(InitialFromFileMixin, Form):
initial_template = "request/initials/template.html" initial_template = "request/initials/template.html"
class LeaseRequestForm(InitialFromFileMixin, Form): class LeaseRequestForm(Form):
lease = ModelChoiceField(LeaseType.objects.all(), label=_("Lease")) lease = ModelChoiceField(LeaseType.objects.all(), label=_("Lease"))
message = CharField(widget=Textarea, label=_("Message")) message = CharField(widget=Textarea(attrs={'placeholder': 'Why do you need this lease?'}), label=_("Message"))
initial_template = "request/initials/lease.html"
class ResourceRequestForm(InitialFromFileMixin, VmResourcesForm): class ResourceRequestForm(InitialFromFileMixin, VmResourcesForm):
......
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2018-05-18 07:30
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('request', '0010_auto_20180517_1638'),
]
operations = [
migrations.AlterField(
model_name='request',
name='closed_by',
field=models.CharField(default=0, max_length=100),
preserve_default=False,
),
]
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
import json import json
import logging import logging
import openstack_api
from django.db.models import ( from django.db.models import (
Model, CharField, IntegerField, TextField, ForeignKey, ManyToManyField, Model, CharField, IntegerField, TextField, ForeignKey, ManyToManyField,
) )
...@@ -38,6 +39,7 @@ from model_utils import Choices ...@@ -38,6 +39,7 @@ from model_utils import Choices
from sizefield.utils import filesizeformat from sizefield.utils import filesizeformat
from vm.models import Instance, InstanceTemplate, Lease from vm.models import Instance, InstanceTemplate, Lease
from vm.models.vm_lease import VmLease
from vm.operations import ResourcesOperation, ResizeDiskOperation from vm.operations import ResourcesOperation, ResizeDiskOperation
from storage.models import Disk from storage.models import Disk
...@@ -81,7 +83,7 @@ class Request(TimeStampedModel): ...@@ -81,7 +83,7 @@ class Request(TimeStampedModel):
status = CharField(choices=STATUSES, default=STATUSES.PENDING, status = CharField(choices=STATUSES, default=STATUSES.PENDING,
max_length=10) max_length=10)
user_id = CharField(blank=False, max_length=100) user_id = CharField(blank=False, max_length=100)
closed_by = ForeignKey(User, related_name="closed_by", null=True) closed_by = CharField(blank=False, max_length=100)
TYPES = Choices( TYPES = Choices(
('resource', _('resource request')), ('resource', _('resource request')),
('lease', _("lease request")), ('lease', _("lease request")),
...@@ -127,20 +129,21 @@ class Request(TimeStampedModel): ...@@ -127,20 +129,21 @@ class Request(TimeStampedModel):
"DECLINED": "times", "DECLINED": "times",
}.get(self.status) }.get(self.status)
def accept(self, user): def accept(self, request):
self.action.accept(user) self.action.accept(request)
self.status = "ACCEPTED" self.status = "ACCEPTED"
self.closed_by = user self.closed_by = request.user.id
self.save() self.save()
self.user.profile.notify( # self.user.profile.notify(
ugettext_noop("Request accepted"), # ugettext_noop("Request accepted"),
self.action.accept_msg # self.action.accept_msg
) # )
# TODO
def decline(self, user, reason): def decline(self, request, reason):
self.status = "DECLINED" self.status = "DECLINED"
self.closed_by = user self.closed_by = request.user.id
self.reason = reason self.reason = reason
self.save() self.save()
...@@ -149,10 +152,11 @@ class Request(TimeStampedModel): ...@@ -149,10 +152,11 @@ class Request(TimeStampedModel):
'following reason: %(reason)s' 'following reason: %(reason)s'
) )
self.user.profile.notify( # self.user.profile.notify(
ugettext_noop("Request declined"), # ugettext_noop("Request declined"),
decline_msg, url=self.get_absolute_url(), reason=self.reason, # decline_msg, url=self.get_absolute_url(), reason=self.reason,
) # )
# TODO
@property @property
def is_acceptable(self): def is_acceptable(self):
...@@ -223,9 +227,9 @@ class ExtendLeaseAction(RequestAction): ...@@ -223,9 +227,9 @@ class ExtendLeaseAction(RequestAction):
os_server_id = CharField(blank=False, max_length=100) os_server_id = CharField(blank=False, max_length=100)
lease_type = ForeignKey(LeaseType) lease_type = ForeignKey(LeaseType)
def accept(self, user): def accept(self, request):
pass instance = openstack_api.nova.server_get(request, self.os_server_id)
# self.instance.renew(lease=self.lease_type.lease, save=True, force=True, user=user) instance.renew.call(request, lease=self.lease_type.lease, save=True, force=True)
@property @property
def accept_msg(self): def accept_msg(self):
......
...@@ -44,11 +44,11 @@ ...@@ -44,11 +44,11 @@
{% if object.type == "lease" %} {% if object.type == "lease" %}
<dl> <dl>
<dt>{% trans "VM name" %}</dt> <dt>{% trans "VM name" %}</dt>
<dd><a href="{{ action.instance.get_absolute_url }}">{{ action.instance.name }}</a></dd> <dd><a href="{% url "dashboard.views.detail" pk=instance.id %}">{{ instance.name }}</a></dd>
<dt>{% trans "VM description" %}</dt> <dt>{% trans "VM description" %}</dt>
<dd>{{ action.instance.description }}</dd> <dd>{{ instance.description }}</dd>
<dt>{% trans "Current lease" %}</dt> <dt>{% trans "Current lease" %}</dt>
<dd>{{ action.instance.lease }}</dd> <dd>{{ current_lease }}</dd>
<dt>{% trans "Requested lease" %}</dt> <dt>{% trans "Requested lease" %}</dt>
<dd>{{ action.lease_type.lease }}</dd> <dd>{{ action.lease_type.lease }}</dd>
</dl> </dl>
...@@ -133,7 +133,7 @@ ...@@ -133,7 +133,7 @@
Are you adding a new action type? Are you adding a new action type?
{% endif %} {% endif %}
{% if object.status == "PENDING" and request.user.is_superuser %} {% if object.status == "PENDING" %}
<hr /> <hr />
<div class="pull-right" id="request-buttons"> <div class="pull-right" id="request-buttons">
......
...@@ -45,6 +45,7 @@ from request.forms import ( ...@@ -45,6 +45,7 @@ from request.forms import (
LeaseTypeForm, TemplateAccessTypeForm, TemplateRequestForm, LeaseTypeForm, TemplateAccessTypeForm, TemplateRequestForm,
LeaseRequestForm, ResourceRequestForm, ResizeRequestForm, LeaseRequestForm, ResourceRequestForm, ResizeRequestForm,
) )
from vm.models.vm_lease import VmLease
class RequestDecideRequiredMixin(AccessMixin): class RequestDecideRequiredMixin(AccessMixin):
...@@ -58,6 +59,7 @@ class RequestDecideRequiredMixin(AccessMixin): ...@@ -58,6 +59,7 @@ class RequestDecideRequiredMixin(AccessMixin):
return super(RequestDecideRequiredMixin, self).dispatch( return super(RequestDecideRequiredMixin, self).dispatch(
request, *args, **kwargs) request, *args, **kwargs)
class RequestList(LoginRequiredMixin, RequestDecideRequiredMixin, SingleTableView): class RequestList(LoginRequiredMixin, RequestDecideRequiredMixin, SingleTableView):
model = Request model = Request
table_class = RequestTable table_class = RequestTable
...@@ -77,7 +79,7 @@ class RequestList(LoginRequiredMixin, RequestDecideRequiredMixin, SingleTableVie ...@@ -77,7 +79,7 @@ class RequestList(LoginRequiredMixin, RequestDecideRequiredMixin, SingleTableVie
return data return data
class RequestDetail(LoginRequiredMixin, DetailView): class RequestDetail(LoginRequiredMixin, RequestDecideRequiredMixin, DetailView):
model = Request model = Request
template_name = "request/detail.html" template_name = "request/detail.html"
...@@ -85,25 +87,18 @@ class RequestDetail(LoginRequiredMixin, DetailView): ...@@ -85,25 +87,18 @@ class RequestDetail(LoginRequiredMixin, DetailView):
user = self.request.user user = self.request.user
request = self.get_object() # not self.request! request = self.get_object() # not self.request!
if not user.is_superuser:
raise SuspiciousOperation
if self.get_object().status == "PENDING": if self.get_object().status == "PENDING":
accept = self.request.POST.get("accept") accept = self.request.POST.get("accept")
reason = self.request.POST.get("reason") reason = self.request.POST.get("reason")
if accept: if accept:
request.accept(user) request.accept(self.request)
else: else:
request.decline(user, reason) request.decline(self.request, reason)
return redirect(request.get_absolute_url()) return redirect(request.get_absolute_url())
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
request = self.object request = self.object
user = self.request.user
if not user.is_superuser and request.user != user:
raise SuspiciousOperation
context = super(RequestDetail, self).get_context_data(**kwargs) context = super(RequestDetail, self).get_context_data(**kwargs)
...@@ -112,6 +107,10 @@ class RequestDetail(LoginRequiredMixin, DetailView): ...@@ -112,6 +107,10 @@ class RequestDetail(LoginRequiredMixin, DetailView):
# workaround for http://git.io/vIIYi # workaround for http://git.io/vIIYi
context['request'] = self.request context['request'] = self.request
if request.type == "lease":
context['instance'] = openstack_api.nova.server_get(self.request, request.action.os_server_id)
context['current_lease'] = VmLease.get_or_create_lease(request.action.os_server_id).lease
return context return context
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment