Commit 2e3d4c2d by Kálmán Viktor

vm: abort activities

note: this doesn't work
parent 3304837c
...@@ -15,6 +15,7 @@ class Operation(object): ...@@ -15,6 +15,7 @@ class Operation(object):
async_queue = 'localhost.man' async_queue = 'localhost.man'
required_perms = () required_perms = ()
do_not_call_in_templates = True do_not_call_in_templates = True
abortable = False
def __call__(self, **kwargs): def __call__(self, **kwargs):
return self.call(**kwargs) return self.call(**kwargs)
......
...@@ -9,6 +9,14 @@ ...@@ -9,6 +9,14 @@
{{ a.get_readable_name }}{% if user.is_superuser %}</a>{% endif %} {{ a.get_readable_name }}{% if user.is_superuser %}</a>{% endif %}
</strong> </strong>
{{ a.started|date:"Y-m-d H:i" }}{% if a.user %}, {{ a.user }}{% endif %} {{ a.started|date:"Y-m-d H:i" }}{% if a.user %}, {{ a.user }}{% endif %}
{% if user.is_superuser and a.is_abortable %}
<form action="" method="POST" class="pull-right">
{% csrf_token %}
<input type="hidden" name="abort_shutdown"/>
<input type="hidden" name="activity" value="{{ a.pk }}"/>
<button class="btn btn-danger btn-xs"><i class="icon-bolt"></i> {% trans "Abort shutdown" %}</button>
</form>
{% endif %}
{% if a.children.count > 0 %} {% if a.children.count > 0 %}
<div class="sub-timeline"> <div class="sub-timeline">
{% for s in a.children.all %} {% for s in a.children.all %}
......
...@@ -243,6 +243,7 @@ class VmDetailView(CheckedDetailView): ...@@ -243,6 +243,7 @@ class VmDetailView(CheckedDetailView):
'to_remove': self.__remove_tag, 'to_remove': self.__remove_tag,
'port': self.__add_port, 'port': self.__add_port,
'new_network_vlan': self.__new_network, 'new_network_vlan': self.__new_network,
'abort_shutdown': self.__abort_shutdown,
} }
for k, v in options.iteritems(): for k, v in options.iteritems():
if request.POST.get(k) is not None: if request.POST.get(k) is not None:
...@@ -428,6 +429,16 @@ class VmDetailView(CheckedDetailView): ...@@ -428,6 +429,16 @@ class VmDetailView(CheckedDetailView):
return redirect("%s#network" % reverse_lazy( return redirect("%s#network" % reverse_lazy(
"dashboard.views.detail", kwargs={'pk': self.object.pk})) "dashboard.views.detail", kwargs={'pk': self.object.pk}))
def __abort_shutdown(self, request):
self.object = self.get_object()
if not request.user.is_superuser:
raise PermissionDenied()
activity = get_object_or_404(InstanceActivity,
pk=request.POST.get("activity"))
activity.abort()
return redirect("%s#activity" % self.object.get_absolute_url())
class OperationView(DetailView): class OperationView(DetailView):
......
...@@ -2,6 +2,8 @@ from __future__ import absolute_import, unicode_literals ...@@ -2,6 +2,8 @@ from __future__ import absolute_import, unicode_literals
from contextlib import contextmanager from contextlib import contextmanager
from logging import getLogger from logging import getLogger
from celery.contrib.abortable import AbortableAsyncResult
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.db.models import CharField, ForeignKey from django.db.models import CharField, ForeignKey
from django.utils import timezone from django.utils import timezone
...@@ -11,6 +13,8 @@ from common.models import ( ...@@ -11,6 +13,8 @@ from common.models import (
ActivityModel, activitycontextimpl, join_activity_code, ActivityModel, activitycontextimpl, join_activity_code,
) )
from manager.mancelery import celery
logger = getLogger(__name__) logger = getLogger(__name__)
...@@ -103,6 +107,13 @@ class InstanceActivity(ActivityModel): ...@@ -103,6 +107,13 @@ class InstanceActivity(ActivityModel):
self.instance._update_status() self.instance._update_status()
return ret return ret
def is_abortable(self):
op = self.instance.get_operation_from_activity_code(self.activity_code)
return False if op is None else (op.abortable and not self.finished)
def abort(self):
AbortableAsyncResult(self.task_uuid, backend=celery.backend).abort()
@contextmanager @contextmanager
def instance_activity(code_suffix, instance, on_abort=None, on_commit=None, def instance_activity(code_suffix, instance, on_abort=None, on_commit=None,
......
...@@ -315,6 +315,7 @@ class ShutdownOperation(InstanceOperation): ...@@ -315,6 +315,7 @@ class ShutdownOperation(InstanceOperation):
id = 'shutdown' id = 'shutdown'
name = _("shutdown") name = _("shutdown")
description = _("Shutdown virtual machine with ACPI signal.") description = _("Shutdown virtual machine with ACPI signal.")
abortable = True
def check_precond(self): def check_precond(self):
super(ShutdownOperation, self).check_precond() super(ShutdownOperation, self).check_precond()
......
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