Commit 46557987 authored by Stevan Radakovic's avatar Stevan Radakovic
Browse files

Add cancel command for TestJob viewset in REST API.

Also refactor the cancel code a bit to be shared across the
multiple APIs.
parent d8bf532e
......@@ -170,6 +170,12 @@ class TestSuiteViewSet(NestedViewSetMixin, viewsets.ReadOnlyModelViewSet):
)
return response
@detail_route(methods=["get"], suffix="cancel")
def cancel(self, request, **kwargs):
# django-rest-framework handles django's PermissionDenied error
# automagically
self.get_object().cancel(request.user)
class TestCaseViewSet(NestedViewSetMixin, viewsets.ReadOnlyModelViewSet):
queryset = TestCase.objects
......
......@@ -197,22 +197,10 @@ class SchedulerAPI(ExposedAPI):
except TestJob.DoesNotExist:
raise xmlrpc.client.Fault(404, "Specified job not found.")
if job.state in [TestJob.STATE_CANCELING, TestJob.STATE_FINISHED]:
# Don't do anything for jobs that ended already
return True
if not job.can_cancel(self.user):
try:
job.cancel(self.user)
except PermissionDenied:
raise xmlrpc.client.Fault(403, "Permission denied.")
if job.is_multinode:
multinode_jobs = TestJob.objects.select_for_update().filter(
target_group=job.target_group
)
for multinode_job in multinode_jobs:
multinode_job.go_state_canceling()
multinode_job.save()
else:
job.go_state_canceling()
job.save()
return True
def validate_yaml(self, yaml_string):
......
......@@ -29,6 +29,7 @@ import gzip
import simplejson
import yaml
from django.db import transaction
from django.db.models import Q
from django.conf import settings
from django.contrib.auth.models import User, Group, Permission
......@@ -36,7 +37,11 @@ from django.contrib.contenttypes.models import ContentType
from django.contrib.admin.models import LogEntry, ADDITION, CHANGE
from django.contrib.postgres.fields import ArrayField
from django.contrib.sites.models import Site
from django.core.exceptions import ImproperlyConfigured, ValidationError
from django.core.exceptions import (
ImproperlyConfigured,
PermissionDenied,
ValidationError,
)
from django.urls import reverse
from django.db import models
from django.utils import timezone
......@@ -2016,6 +2021,24 @@ class TestJob(models.Model):
retval.append({attribute.name: attribute.value})
return retval
@transaction.atomic
def cancel(self, user):
if not self.can_cancel(user):
raise PermissionDenied("Insufficient permissions")
if self.state in [TestJob.STATE_CANCELING, TestJob.STATE_FINISHED]:
# Don't do anything for jobs that ended already
return
if self.is_multinode:
multinode_jobs = TestJob.objects.select_for_update().filter(
target_group=self.target_group
)
for multinode_job in multinode_jobs:
multinode_job.go_state_canceling()
multinode_job.save()
else:
self.go_state_canceling()
self.save()
class Notification(models.Model):
......
......@@ -1705,25 +1705,16 @@ def job_log_incremental(request, pk):
return response
@transaction.atomic
def job_cancel(request, pk):
with transaction.atomic():
job = get_restricted_job(request.user, pk, request=request, for_update=True)
if job.can_cancel(request.user):
if job.is_multinode:
multinode_jobs = TestJob.objects.select_for_update().filter(
target_group=job.target_group
)
for multinode_job in multinode_jobs:
multinode_job.go_state_canceling()
multinode_job.save()
else:
job.go_state_canceling()
job.save()
return redirect(job)
else:
return HttpResponseForbidden(
"you cannot cancel this job", content_type="text/plain"
)
job = get_restricted_job(request.user, pk, request=request, for_update=True)
try:
job.cancel(request.user)
return redirect(job)
except PermissionDenied:
return HttpResponseForbidden(
"you cannot cancel this job", content_type="text/plain"
)
def job_fail(request, pk):
......
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 to comment