Commit 04beb592 by Bach Dániel

Merge branch 'fix-disk-delete' into 'master'

Disk delete as op view

Closes #201

See merge request !228
parents 0c61f4e0 5101d440
......@@ -40,6 +40,7 @@ from django.contrib.auth.forms import UserCreationForm as OrgUserCreationForm
from django.forms.widgets import TextInput, HiddenInput
from django.template import Context
from django.template.loader import render_to_string
from django.utils.html import escape
from django.utils.translation import ugettext_lazy as _
from sizefield.widgets import FileSizeWidget
from django.core.urlresolvers import reverse_lazy
......@@ -852,11 +853,40 @@ class VmDiskResizeForm(forms.Form):
helper.form_tag = False
if self.disk:
helper.layout = Layout(
HTML(_("<label>Disk:</label> %s") % self.disk),
HTML(_("<label>Disk:</label> %s") % escape(self.disk)),
Field('disk'), Field('size'))
return helper
class VmDiskRemoveForm(forms.Form):
def __init__(self, *args, **kwargs):
choices = kwargs.pop('choices')
self.disk = kwargs.pop('default')
super(VmDiskRemoveForm, self).__init__(*args, **kwargs)
self.fields.insert(0, 'disk', forms.ModelChoiceField(
queryset=choices, initial=self.disk, required=True,
empty_label=None, label=_('Disk')))
if self.disk:
self.fields['disk'].widget = HiddenInput()
@property
def helper(self):
helper = FormHelper(self)
helper.form_tag = False
if self.disk:
helper.layout = Layout(
AnyTag(
"div",
HTML(_("<label>Disk:</label> %s") % escape(self.disk)),
css_class="form-group",
),
Field("disk"),
)
return helper
class VmDownloadDiskForm(forms.Form):
name = forms.CharField(max_length=100, label=_("Name"), required=False)
url = forms.CharField(label=_('URL'), validators=[URLValidator(), ])
......
{% load i18n %}
{% load sizefieldtags %}
<i class="fa {% if d.is_downloading %}fa-refresh fa-spin{% else %}fa-file{% if d.failed %}" style="color: #d9534f;{% endif %}{% endif %}"></i>
{{ d.name }} (#{{ d.id }}) -
{% if not d.is_downloading %}
{% if not d.failed %}
{% if d.size %}{{ d.size|filesize }}{% endif %}
{% else %}
<div class="label label-danger"{% if user.is_superuser %} title="{{ d.get_latest_activity_result }}"{% endif %}>{% trans "failed" %}</div>
{% endif %}
{% else %}<span class="disk-list-disk-percentage" data-disk-pk="{{ d.pk }}">{{ d.get_download_percentage }}</span>%{% endif %}
{% if is_owner != False %}
<a href="{% url "dashboard.views.disk-remove" pk=d.pk %}?next={{ request.path }}"
data-disk-pk="{{ d.pk }}" class="btn btn-xs btn-danger pull-right disk-remove"
{% if not long_remove %}title="{% trans "Remove" %}"{% endif %}>
<i class="fa fa-times"></i>{% if long_remove %} {% trans "Remove" %}{% endif %}
<i class="fa fa-file"></i>
{{ d.name }} (#{{ d.id }})
{% if op.remove_disk %}
<span class="operation-wrapper">
<a href="{{ op.remove_disk.get_url }}?disk={{d.pk}}"
class="btn btn-xs btn-{{ op.remove_disk.effect}} pull-right operation disk-remove-btn
{% if op.resize_disk.disabled %}disabled{% endif %}">
<i class="fa fa-{{ op.remove_disk.icon }}"></i> {% trans "Remove" %}
</a>
{% if op.resize_disk %}
</span>
{% endif %}
{% if op.resize_disk %}
<span class="operation-wrapper">
<a href="{{ op.resize_disk.get_url }}?disk={{d.pk}}"
class="btn btn-xs btn-warning pull-right operation disk-resize-btn">
<i class="fa fa-arrows-alt"></i> {% trans "Resize" %}
class="btn btn-xs btn-{{ op.resize_disk.effect }} pull-right operation disk-resize-btn
{% if op.resize_disk.disabled %}disabled{% endif %}">
<i class="fa fa-{{ op.resize_disk.icon }}"></i> {% trans "Resize" %}
</a>
</span>
{% endif %}
{% endif %}
<div style="clear: both;"></div>
......@@ -86,7 +86,13 @@
{% endif %}
{% for d in disks %}
<li>
{% include "dashboard/_disk-list-element.html" %}
<i class="fa fa-file"></i>
{{ d.name }} (#{{ d.id }}) -
<a href="{% url "dashboard.views.disk-remove" pk=d.pk %}?next={{ request.path }}"
data-disk-pk="{{ d.pk }}" class="btn btn-xs btn-danger pull-right disk-remove"
{% if not long_remove %}title="{% trans "Remove" %}"{% endif %}>
<i class="fa fa-times"></i>{% if long_remove %} {% trans "Remove" %}{% endif %}
</a>
</li>
{% endfor %}
</ul>
......
......@@ -37,6 +37,7 @@ from braces.views import (
from django_tables2 import SingleTableView
from vm.models import InstanceTemplate, InterfaceTemplate, Instance, Lease
from storage.models import Disk
from ..forms import (
TemplateForm, TemplateListSearchForm, AclUserOrGroupAddForm, LeaseForm,
......@@ -319,6 +320,57 @@ class TemplateDetail(LoginRequiredMixin, SuccessMessageMixin, UpdateView):
return kwargs
class DiskRemoveView(DeleteView):
model = Disk
def get_queryset(self):
qs = super(DiskRemoveView, self).get_queryset()
return qs.exclude(template_set=None)
def get_template_names(self):
if self.request.is_ajax():
return ['dashboard/confirm/ajax-delete.html']
else:
return ['dashboard/confirm/base-delete.html']
def get_context_data(self, **kwargs):
context = super(DiskRemoveView, self).get_context_data(**kwargs)
disk = self.get_object()
template = disk.template_set.get()
if not template.has_level(self.request.user, 'owner'):
raise PermissionDenied()
context['title'] = _("Disk remove confirmation")
context['text'] = _("Are you sure you want to remove "
"<strong>%(disk)s</strong> from "
"<strong>%(app)s</strong>?" % {'disk': disk,
'app': template}
)
return context
def delete(self, request, *args, **kwargs):
disk = self.get_object()
template = disk.template_set.get()
if not template.has_level(request.user, 'owner'):
raise PermissionDenied()
template.remove_disk(disk=disk, user=request.user)
disk.destroy()
next_url = request.POST.get("next")
success_url = next_url if next_url else template.get_absolute_url()
success_message = _("Disk successfully removed.")
if request.is_ajax():
return HttpResponse(
json.dumps({'message': success_message}),
content_type="application/json",
)
else:
messages.success(request, success_message)
return HttpResponseRedirect("%s#resources" % success_url)
class LeaseCreate(LoginRequiredMixin, PermissionRequiredMixin,
SuccessMessageMixin, CreateView):
model = Lease
......
......@@ -59,7 +59,7 @@ from ..forms import (
AclUserOrGroupAddForm, VmResourcesForm, TraitsForm, RawDataForm,
VmAddInterfaceForm, VmCreateDiskForm, VmDownloadDiskForm, VmSaveForm,
VmRenewForm, VmStateChangeForm, VmListSearchForm, VmCustomizeForm,
TransferOwnershipForm, VmDiskResizeForm, RedeployForm,
TransferOwnershipForm, VmDiskResizeForm, RedeployForm, VmDiskRemoveForm,
)
from ..models import Favourite, Profile
......@@ -370,13 +370,8 @@ class VmAddInterfaceView(FormOperationMixin, VmOperationView):
return val
class VmDiskResizeView(FormOperationMixin, VmOperationView):
op = 'resize_disk'
form_class = VmDiskResizeForm
class VmDiskModifyView(FormOperationMixin, VmOperationView):
show_in_toolbar = False
icon = 'arrows-alt'
effect = "success"
def get_form_kwargs(self):
choices = self.get_op().instance.disks
......@@ -389,7 +384,7 @@ class VmDiskResizeView(FormOperationMixin, VmOperationView):
else:
default = None
val = super(VmDiskResizeView, self).get_form_kwargs()
val = super(VmDiskModifyView, self).get_form_kwargs()
val.update({'choices': choices, 'default': default})
return val
......@@ -662,7 +657,12 @@ vm_ops = OrderedDict([
op='destroy', icon='times', effect='danger')),
('create_disk', VmCreateDiskView),
('download_disk', VmDownloadDiskView),
('resize_disk', VmDiskResizeView),
('resize_disk', VmDiskModifyView.factory(
op='resize_disk', form_class=VmDiskResizeForm,
icon='arrows-alt', effect="warning")),
('remove_disk', VmDiskModifyView.factory(
op='remove_disk', form_class=VmDiskRemoveForm,
icon='times', effect="danger")),
('add_interface', VmAddInterfaceView),
('renew', VmRenewView),
('resources_change', VmResourcesChangeView),
......@@ -1126,51 +1126,6 @@ class InstanceActivityDetail(CheckedDetailView):
return ctx
class DiskRemoveView(DeleteView):
model = Disk
def get_template_names(self):
if self.request.is_ajax():
return ['dashboard/confirm/ajax-delete.html']
else:
return ['dashboard/confirm/base-delete.html']
def get_context_data(self, **kwargs):
context = super(DiskRemoveView, self).get_context_data(**kwargs)
disk = self.get_object()
app = disk.get_appliance()
context['title'] = _("Disk remove confirmation")
context['text'] = _("Are you sure you want to remove "
"<strong>%(disk)s</strong> from "
"<strong>%(app)s</strong>?" % {'disk': disk,
'app': app}
)
return context
def delete(self, request, *args, **kwargs):
disk = self.get_object()
app = disk.get_appliance()
if not app.has_level(request.user, 'owner'):
raise PermissionDenied()
app.remove_disk(disk=disk, user=request.user)
disk.destroy()
next_url = request.POST.get("next")
success_url = next_url if next_url else app.get_absolute_url()
success_message = _("Disk successfully removed.")
if request.is_ajax():
return HttpResponse(
json.dumps({'message': success_message}),
content_type="application/json",
)
else:
messages.success(request, success_message)
return HttpResponseRedirect("%s#resources" % success_url)
@require_GET
def get_disk_download_status(request, pk):
disk = Disk.objects.get(pk=pk)
......
......@@ -575,6 +575,7 @@ class RemoveDiskOperation(InstanceOperation):
'destroy_disk',
readable_name=ugettext_noop('destroy disk')
):
disk.destroy()
return self.instance.disks.remove(disk)
def get_activity_name(self, kwargs):
......
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