=== added file 'lava_scheduler_app/api.py'
@@ -0,0 +1,15 @@
+import xmlrpclib
+
+from linaro_django_xmlrpc.models import ExposedAPI
+
+from lava_scheduler_app.models import TestJob
+
+
+class SchedulerAPI(ExposedAPI):
+
+ def submit_job(self, job_data):
+ if not self.user:
+ raise xmlrpclib.Fault(401, "Authentication required.")
+ if not self.user.has_perm('lava_scheduler_app.add_testjob'):
+ raise xmlrpclib.Fault(403, "Permission denied.")
+ return TestJob.from_json_and_user(job_data, self.user).id
=== modified file 'lava_scheduler_app/extension.py'
@@ -33,6 +33,11 @@
return "lava_scheduler_app"
@property
+ def api_class(self):
+ from lava_scheduler_app.api import SchedulerAPI
+ return SchedulerAPI
+
+ @property
def name(self):
return "Scheduler"
=== modified file 'lava_scheduler_app/tests.py'
@@ -1,11 +1,38 @@
import datetime
import json
+import xmlrpclib
-from django.contrib.auth.models import User
+from django.contrib.auth.models import Permission, User
from django.test import TestCase
from lava_scheduler_app.models import Device, DeviceType, TestJob
+import cStringIO
+
+from xmlrpclib import ServerProxy, Transport
+
+from django.test.client import Client
+
+# Based on http://www.technobabble.dk/2008/apr/02/xml-rpc-dispatching-through-django-test-client/
+class TestTransport(Transport):
+ """Handles connections to XML-RPC server through Django test client."""
+
+ def __init__(self, user=None, password=None):
+ self.client = Client()
+ if user:
+ success = self.client.login(username=user, password=password)
+ if not success:
+ raise AssertionError("Login attempt failed!")
+ self._use_datetime = True
+
+ def request(self, host, handler, request_body, verbose=0):
+ self.verbose = verbose
+ response = self.client.post(
+ handler, request_body, content_type="text/xml")
+ res = cStringIO.StringIO(response.content)
+ res.seek(0)
+ return self.parse_response(res)
+
class TestTestJob(TestCase):
@@ -60,3 +87,42 @@
job = TestJob.from_json_and_user(
json.dumps({'device_type':'panda'}), self.make_user())
self.assertEqual(job.status, TestJob.SUBMITTED)
+
+
+class TestSchedulerAPI(TestCase):
+
+ def server_proxy(self, user=None, password=None):
+ return ServerProxy(
+ 'http://localhost/RPC2/',
+ transport=TestTransport(user=user, password=password))
+
+ def test_api_rejects_anonymous(self):
+ server = self.server_proxy()
+ try:
+ server.scheduler.submit_job("{}")
+ except xmlrpclib.Fault as f:
+ self.assertEqual(401, f.faultCode)
+ else:
+ self.fail("fault not raised")
+
+ def test_api_rejects_unpriv_user(self):
+ User.objects.create_user('test', 'e@mail.invalid', 'test').save()
+ server = self.server_proxy('test', 'test')
+ try:
+ server.scheduler.submit_job("{}")
+ except xmlrpclib.Fault as f:
+ self.assertEqual(403, f.faultCode)
+ else:
+ self.fail("fault not raised")
+
+ def test_sets_definition(self):
+ user = User.objects.create_user('test', 'e@mail.invalid', 'test')
+ user.user_permissions.add(
+ Permission.objects.get(codename='add_testjob'))
+ user.save()
+ server = self.server_proxy('test', 'test')
+ DeviceType.objects.get_or_create(name='panda')
+ definition = json.dumps({'device_type':'panda'})
+ job_id = server.scheduler.submit_job(definition)
+ job = TestJob.objects.get(id=job_id)
+ self.assertEqual(definition, job.definition)